hecks 2.8.0 → 3.0.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 (886) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +50 -7
  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 +32 -100
  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 +10 -32
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
  25. data/lib/hecks/adapters/driven/postgres.rb +149 -136
  26. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  27. data/lib/hecks/adapters/driven/prism.rb +48 -38
  28. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  29. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  30. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  31. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  32. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  33. data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
  34. data/lib/hecks/adapters/driven.rb +5 -36
  35. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  36. data/lib/hecks/behaviors/dsl.rb +7 -25
  37. data/lib/hecks/behaviors/expectations.rb +32 -142
  38. data/lib/hecks/behaviors/ir.rb +7 -20
  39. data/lib/hecks/behaviors/rspec.rb +6 -17
  40. data/lib/hecks/behaviors/runner.rb +10 -34
  41. data/lib/hecks/behaviors.rb +4 -8
  42. data/lib/hecks/bench/cli.rb +62 -0
  43. data/lib/hecks/bench/environment.rb +71 -0
  44. data/lib/hecks/bench/postgres_probe.rb +30 -0
  45. data/lib/hecks/bench/report.rb +76 -0
  46. data/lib/hecks/bench/ruby_runner.rb +93 -0
  47. data/lib/hecks/bench/run.rb +55 -0
  48. data/lib/hecks/bench/rust_runner.rb +101 -0
  49. data/lib/hecks/bench/stats.rb +46 -0
  50. data/lib/hecks/bench/suite.rb +98 -0
  51. data/lib/hecks/bench/workload.rb +89 -0
  52. data/lib/hecks/bench.rb +17 -0
  53. data/lib/hecks/bluebook/aggregate.rb +9 -75
  54. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  55. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  56. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  57. data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
  58. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  59. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  60. data/lib/hecks/bluebook/assembly.rb +6 -45
  61. data/lib/hecks/bluebook/attribute.rb +12 -61
  62. data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
  63. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  64. data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
  65. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  66. data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
  67. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  68. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  69. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  70. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  71. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
  73. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  74. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  75. data/lib/hecks/bluebook/capabilities.rb +17 -49
  76. data/lib/hecks/bluebook/chapter.rb +16 -50
  77. data/lib/hecks/bluebook/command.rb +23 -81
  78. data/lib/hecks/bluebook/domain_port.rb +49 -67
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  80. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  81. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  82. data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
  83. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
  84. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
  85. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
  86. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  87. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  88. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
  89. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  90. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  91. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
  92. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  93. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  94. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  95. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  96. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  97. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  98. data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
  99. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  100. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  101. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  102. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  103. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  104. data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
  105. data/lib/hecks/bluebook/entity.rb +13 -71
  106. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  107. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  108. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  109. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  110. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  111. data/lib/hecks/bluebook/expression/resolver.rb +39 -661
  112. data/lib/hecks/bluebook/hexagon.rb +18 -33
  113. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  114. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  115. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  116. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  117. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  118. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  119. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
  120. data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
  121. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
  122. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  123. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
  124. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  125. data/lib/hecks/bluebook/meta_validator.rb +87 -352
  126. data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
  127. data/lib/hecks/bluebook/model_check.rb +122 -596
  128. data/lib/hecks/bluebook/pattern_subset.rb +49 -69
  129. data/lib/hecks/bluebook/process_manager.rb +13 -83
  130. data/lib/hecks/bluebook/project_loader.rb +3 -39
  131. data/lib/hecks/bluebook/project_register.rb +12 -60
  132. data/lib/hecks/bluebook/query.rb +27 -51
  133. data/lib/hecks/bluebook/read_model.rb +57 -81
  134. data/lib/hecks/bluebook/reference.rb +7 -41
  135. data/lib/hecks/bluebook/smoke_test.rb +9 -99
  136. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  137. data/lib/hecks/bluebook/translation.rb +26 -62
  138. data/lib/hecks/bluebook/value_object.rb +11 -36
  139. data/lib/hecks/bluebook.rb +5 -22
  140. data/lib/hecks/cache_dir.rb +4 -23
  141. data/lib/hecks/canonical_json.rb +30 -0
  142. data/lib/hecks/chapters.rb +102 -0
  143. data/lib/hecks/cli/behaviors.rb +61 -0
  144. data/lib/hecks/cli/canonicalise.rb +25 -0
  145. data/lib/hecks/cli/check_engine_agreement.rb +32 -0
  146. data/lib/hecks/cli/check_era.rb +88 -0
  147. data/lib/hecks/cli/console.rb +66 -0
  148. data/lib/hecks/cli/deploy_template_diff.rb +40 -0
  149. data/lib/hecks/cli/doc_coverage.rb +32 -0
  150. data/lib/hecks/cli/document.rb +5 -23
  151. data/lib/hecks/cli/expression_projection.rb +41 -0
  152. data/lib/hecks/cli/follow.rb +88 -0
  153. data/lib/hecks/cli/history.rb +44 -0
  154. data/lib/hecks/cli/ir.rb +4 -6
  155. data/lib/hecks/cli/mcp.rb +5 -6
  156. data/lib/hecks/cli/model_check.rb +24 -88
  157. data/lib/hecks/cli/pattern_cases.rb +47 -0
  158. data/lib/hecks/cli/present.rb +39 -0
  159. data/lib/hecks/cli/project_cli.rb +223 -64
  160. data/lib/hecks/cli/project_diagrams.rb +4 -10
  161. data/lib/hecks/cli/project_glossary.rb +44 -0
  162. data/lib/hecks/cli/reference.rb +46 -0
  163. data/lib/hecks/cli/refresh_projections.rb +44 -0
  164. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
  165. data/lib/hecks/cli/release.rb +70 -0
  166. data/lib/hecks/cli/release_gem.rb +59 -0
  167. data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
  168. data/lib/hecks/cli/rspec_shard_files.rb +66 -0
  169. data/lib/hecks/cli/run.rb +15 -61
  170. data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
  171. data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
  172. data/lib/hecks/cli/shape.rb +70 -0
  173. data/lib/hecks/cli/smoke_http.rb +230 -0
  174. data/lib/hecks/cli/smoke_test.rb +7 -19
  175. data/lib/hecks/cli/spec_example.rb +27 -0
  176. data/lib/hecks/cli/statements.rb +32 -0
  177. data/lib/hecks/cli/stores.rb +4 -6
  178. data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
  179. data/lib/hecks/cli.rb +216 -73
  180. data/lib/hecks/codemod.rb +324 -0
  181. data/lib/hecks/construct.rb +8 -34
  182. data/lib/hecks/corpus.rb +423 -0
  183. data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
  184. data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
  185. data/lib/hecks/deploy/oidc.json +82 -2
  186. data/lib/hecks/doc/reference.rb +351 -0
  187. data/lib/hecks/doors/cli_door.rb +196 -0
  188. data/lib/hecks/doors/cli_runner.rb +297 -0
  189. data/lib/hecks/{facade → doors}/command_request.rb +14 -34
  190. data/lib/hecks/doors/handle.rb +206 -0
  191. data/lib/hecks/doors/json_door.rb +132 -0
  192. data/lib/hecks/doors/launcher_options.rb +129 -0
  193. data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
  194. data/lib/hecks/doors/mcp_door_scope.rb +97 -0
  195. data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
  196. data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
  197. data/lib/hecks/doors/ruby_door.rb +77 -0
  198. data/lib/hecks/doors.rb +61 -0
  199. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  200. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  201. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  202. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  203. data/lib/hecks/embryonaut_bluebook.rb +5 -72
  204. data/lib/hecks/engine_agreement.rb +156 -0
  205. data/lib/hecks/facade.rb +23 -51
  206. data/lib/hecks/forms/app.rb +21 -76
  207. data/lib/hecks/forms/banking_presentation.rb +50 -0
  208. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  209. data/lib/hecks/forms/field_renderer.rb +17 -156
  210. data/lib/hecks/forms/field_shape.rb +31 -222
  211. data/lib/hecks/forms/html.rb +12 -47
  212. data/lib/hecks/forms/index_renderer.rb +1 -4
  213. data/lib/hecks/forms/page.rb +3 -9
  214. data/lib/hecks/forms/params.rb +14 -60
  215. data/lib/hecks/forms/port_argument.rb +2 -19
  216. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  217. data/lib/hecks/forms/record_renderer.rb +8 -75
  218. data/lib/hecks/forms/record_table.rb +7 -50
  219. data/lib/hecks/forms/reference_options.rb +3 -30
  220. data/lib/hecks/forms/value_object_shape.rb +8 -35
  221. data/lib/hecks/forms.rb +5 -33
  222. data/lib/hecks/fqn.rb +5 -12
  223. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  224. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  225. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  226. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  227. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  228. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  229. data/lib/hecks/framework.rb +11 -80
  230. data/lib/hecks/freezer.rb +5 -39
  231. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
  232. data/lib/hecks/fuzzing/combination_miner.rb +86 -0
  233. data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
  234. data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
  235. data/lib/hecks/fuzzing/differential.rb +156 -0
  236. data/lib/hecks/fuzzing/domain_generator.rb +615 -0
  237. data/lib/hecks/fuzzing/era_boundary.rb +71 -0
  238. data/lib/hecks/fuzzing/form_census.rb +136 -0
  239. data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
  240. data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
  241. data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
  242. data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
  243. data/lib/hecks/fuzzing/outside_world.rb +45 -0
  244. data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
  245. data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
  246. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
  247. data/lib/hecks/fuzzing/properties/guards.rb +190 -0
  248. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
  249. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
  250. data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
  251. data/lib/hecks/fuzzing/properties/querying.rb +175 -0
  252. data/lib/hecks/fuzzing/properties.rb +162 -0
  253. data/lib/hecks/fuzzing/qa_settings.rb +123 -0
  254. data/lib/hecks/fuzzing/replay.rb +505 -0
  255. data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
  256. data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
  257. data/lib/hecks/fuzzing/self_consistency.rb +339 -0
  258. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
  259. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
  260. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
  261. data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
  262. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
  263. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
  264. data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
  265. data/lib/hecks/fuzzing/shrinker.rb +166 -0
  266. data/lib/hecks/fuzzing/structural_skips.rb +33 -0
  267. data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
  268. data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
  269. data/lib/hecks/fuzzing/value_generator.rb +216 -0
  270. data/lib/hecks/fuzzing.rb +23 -0
  271. data/lib/hecks/grammar/evolve.rb +336 -0
  272. data/lib/hecks/grammar/expression.bluebook +15 -40
  273. data/lib/hecks/grammar/translation.bluebook +3 -6
  274. data/lib/hecks/grammar.rb +16 -41
  275. data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
  276. data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
  277. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
  278. data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
  279. data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
  280. data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
  281. data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
  282. data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
  283. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
  284. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
  285. data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
  286. data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
  287. data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
  288. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
  289. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
  290. data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
  291. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
  292. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
  293. data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
  294. data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
  295. data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
  296. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
  297. data/lib/hecks/hecks/adapters/git.adapter +7 -0
  298. data/lib/hecks/hecks/adapters/git.rb +102 -0
  299. data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
  300. data/lib/hecks/hecks/adapters/host_http.rb +65 -0
  301. data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
  302. data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
  303. data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
  304. data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
  305. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
  306. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
  307. data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
  308. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
  309. data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
  310. data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
  311. data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
  312. data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
  313. data/lib/hecks/hecks/adapters/local_files.rb +46 -0
  314. data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
  315. data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
  316. data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
  317. data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
  318. data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
  319. data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
  320. data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
  321. data/lib/hecks/hecks/adapters/shell.adapter +7 -0
  322. data/lib/hecks/hecks/adapters/shell.rb +49 -0
  323. data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
  324. data/lib/hecks/hecks/adapters/terminal.rb +74 -0
  325. data/lib/hecks/hecks/codebase.behaviors +172 -0
  326. data/lib/hecks/hecks/codebase.bluebook +2453 -0
  327. data/lib/hecks/hecks/context_map.hecksagon +13 -0
  328. data/lib/hecks/hecks/custodian.behaviors +179 -0
  329. data/lib/hecks/hecks/custodian.bluebook +1847 -0
  330. data/lib/hecks/hecks/deploy.behaviors +74 -0
  331. data/lib/hecks/hecks/deploy.world +12 -0
  332. data/lib/hecks/hecks/environments/memory.world +10 -0
  333. data/lib/hecks/hecks/governance.world +7 -0
  334. data/lib/hecks/hecks/hecks.behaviors +62 -0
  335. data/lib/hecks/hecks/hecks.bluebook +124 -0
  336. data/lib/hecks/hecks/hecks.hecksagon +390 -0
  337. data/lib/hecks/hecks/hecks.world +42 -0
  338. data/lib/hecks/ir.rb +14 -83
  339. data/lib/hecks/kernel_capabilities.rb +194 -0
  340. data/lib/hecks/language/adapter.bluebook +2 -7
  341. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  342. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  343. data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
  344. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  345. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  346. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  347. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  348. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  349. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  350. data/lib/hecks/language/bluebook/query.bluebook +19 -43
  351. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  352. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  353. data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
  354. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  355. data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
  356. data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
  357. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  358. data/lib/hecks/language/oidc.json +35 -0
  359. data/lib/hecks/language/port.bluebook +4 -17
  360. data/lib/hecks/language/translation/translation.bluebook +3 -9
  361. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  362. data/lib/hecks/language/world/wiring.bluebook +1 -3
  363. data/lib/hecks/language/world/world.bluebook +5 -7
  364. data/lib/hecks/literal.rb +8 -50
  365. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  366. data/lib/hecks/naming.rb +29 -137
  367. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
  368. data/lib/hecks/persistence_legacy_fixture.rb +113 -0
  369. data/lib/hecks/ports/access_control.rb +7 -23
  370. data/lib/hecks/ports/agent/answers.rb +5 -23
  371. data/lib/hecks/ports/agent.rb +47 -172
  372. data/lib/hecks/ports/authentication.rb +12 -39
  373. data/lib/hecks/ports/authorization.rb +16 -43
  374. data/lib/hecks/ports/clock.rb +5 -45
  375. data/lib/hecks/ports/extraction.rb +7 -12
  376. data/lib/hecks/ports/identity_assignment.rb +8 -29
  377. data/lib/hecks/ports/identity_generation.rb +6 -29
  378. data/lib/hecks/ports/identity_resolution.rb +2 -10
  379. data/lib/hecks/ports/key_vault.rb +9 -45
  380. data/lib/hecks/ports/persistence/append_only.rb +61 -64
  381. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  382. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  383. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  384. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  385. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
  386. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  387. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
  388. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
  389. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
  390. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  391. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  392. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  393. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  394. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  395. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  396. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  397. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  398. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
  399. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  400. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  401. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  402. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  403. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  404. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
  405. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  406. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
  407. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  408. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
  409. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  410. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  411. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  412. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  413. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  414. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
  415. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
  416. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  417. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  418. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  419. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  420. data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
  421. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  422. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  423. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  424. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  425. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  426. data/lib/hecks/ports/persistence/state_codec.rb +47 -108
  427. data/lib/hecks/ports/persistence.rb +7 -14
  428. data/lib/hecks/ports/projection.rb +42 -84
  429. data/lib/hecks/ports/query/in_memory.rb +10 -58
  430. data/lib/hecks/ports/query/ordering.rb +11 -32
  431. data/lib/hecks/ports/query.rb +14 -37
  432. data/lib/hecks/ports.rb +2 -8
  433. data/lib/hecks/projection_files.rb +285 -0
  434. data/lib/hecks/projections/bootstrap_table.rb +12 -44
  435. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  436. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  437. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  438. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  439. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  440. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  441. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  442. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  443. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  444. data/lib/hecks/projections/deploy/fargate.rb +40 -207
  445. data/lib/hecks/projections/deploy/lambda.rb +191 -708
  446. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  447. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  448. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  449. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  450. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  451. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  452. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  453. data/lib/hecks/projections/deploy/preview/template.rb +3 -59
  454. data/lib/hecks/projections/deploy/preview.rb +2 -67
  455. data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
  456. data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
  457. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
  458. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  459. data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
  460. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  461. data/lib/hecks/projections/deploy/shared.rb +48 -147
  462. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  463. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  464. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  465. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  466. data/lib/hecks/projections/diagrams.rb +22 -584
  467. data/lib/hecks/projections/glossary/html.rb +14 -130
  468. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  469. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  470. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  471. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  472. data/lib/hecks/projections/glossary.rb +30 -222
  473. data/lib/hecks/projections/ir.rb +3 -10
  474. data/lib/hecks/projections/model/deviations.rb +16 -43
  475. data/lib/hecks/projections/model.rb +12 -51
  476. data/lib/hecks/projections/oidc.rb +12 -56
  477. data/lib/hecks/projections/parser_table.rb +13 -32
  478. data/lib/hecks/projections/reference.rb +4 -18
  479. data/lib/hecks/projections/rust_vocabulary.rb +13 -251
  480. data/lib/hecks/projections/shape.rb +3 -29
  481. data/lib/hecks/projections/statements.rb +7 -86
  482. data/lib/hecks/projections/vocabulary.rb +6 -22
  483. data/lib/hecks/projections.rb +2 -16
  484. data/lib/hecks/projector/cli_projector.rb +154 -400
  485. data/lib/hecks/projector/docs_projector.rb +10 -201
  486. data/lib/hecks/projector/exporter.rb +42 -134
  487. data/lib/hecks/projector/ir_projector.rb +2 -9
  488. data/lib/hecks/projector/narrate_projector.rb +15 -189
  489. data/lib/hecks/projector/target.rb +13 -76
  490. data/lib/hecks/projector.rb +30 -121
  491. data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
  492. data/lib/hecks/quality_control/adapters/agent.rb +58 -0
  493. data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
  494. data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
  495. data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
  496. data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
  497. data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
  498. data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
  499. data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
  500. data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
  501. data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
  502. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
  503. data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
  504. data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
  505. data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
  506. data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
  507. data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
  508. data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
  509. data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
  510. data/lib/hecks/quality_control/cli/child.rb +45 -0
  511. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
  512. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
  513. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
  514. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
  515. data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
  516. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
  517. data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
  518. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
  519. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
  520. data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
  521. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
  522. data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
  523. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
  524. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
  525. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
  526. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
  527. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
  528. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
  529. data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
  530. data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
  531. data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
  532. data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
  533. data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
  534. data/lib/hecks/query_ir.rb +346 -0
  535. data/lib/hecks/query_ir_mcp.rb +198 -0
  536. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  537. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  538. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  539. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  540. data/lib/hecks/query_specification/common/options.rb +2 -6
  541. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  542. data/lib/hecks/query_specification/field_path.rb +37 -77
  543. data/lib/hecks/query_specification/hop_path.rb +12 -76
  544. data/lib/hecks/release/gem_pin.rb +2 -26
  545. data/lib/hecks/release/runner/ci_publisher.rb +5 -8
  546. data/lib/hecks/release/runner/clean_tree.rb +42 -0
  547. data/lib/hecks/release/runner/commands.rb +2 -4
  548. data/lib/hecks/release/runner/console.rb +6 -0
  549. data/lib/hecks/release/runner/gem_publisher.rb +15 -9
  550. data/lib/hecks/release/runner/npm_publisher.rb +9 -53
  551. data/lib/hecks/release/runner/preflight.rb +29 -20
  552. data/lib/hecks/release/runner/published.rb +8 -26
  553. data/lib/hecks/release/runner/tagger.rb +31 -23
  554. data/lib/hecks/release/runner.rb +60 -38
  555. data/lib/hecks/rendering.rb +4 -26
  556. data/lib/hecks/router/namespace_installer.rb +15 -39
  557. data/lib/hecks/router.rb +4 -8
  558. data/lib/hecks/runtime/adapter_lookup.rb +124 -0
  559. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  560. data/lib/hecks/runtime/boot_gates.rb +3 -18
  561. data/lib/hecks/runtime/caller.rb +19 -59
  562. data/lib/hecks/runtime/capability_graph.rb +5 -21
  563. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  564. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
  565. data/lib/hecks/runtime/command_interpreter.rb +124 -306
  566. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  567. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  568. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  569. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  570. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  571. data/lib/hecks/runtime/dependency_planning.rb +50 -104
  572. data/lib/hecks/runtime/dispatcher.rb +134 -243
  573. data/lib/hecks/runtime/entity_element.rb +40 -462
  574. data/lib/hecks/runtime/entity_interpreter.rb +64 -219
  575. data/lib/hecks/runtime/errors.rb +32 -115
  576. data/lib/hecks/runtime/event.rb +3 -25
  577. data/lib/hecks/runtime/identity.rb +18 -154
  578. data/lib/hecks/runtime/instance.rb +18 -150
  579. data/lib/hecks/runtime/interpreting.rb +14 -70
  580. data/lib/hecks/runtime/invocation.rb +28 -164
  581. data/lib/hecks/runtime/loader.rb +109 -194
  582. data/lib/hecks/runtime/outbox.rb +39 -262
  583. data/lib/hecks/runtime/policy_interpreter.rb +43 -202
  584. data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
  585. data/lib/hecks/runtime/query_interpreter.rb +122 -187
  586. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  587. data/lib/hecks/runtime/reaction_outcome.rb +89 -0
  588. data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
  589. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  590. data/lib/hecks/runtime/reference_hop.rb +8 -81
  591. data/lib/hecks/runtime/refusal_wording.rb +28 -87
  592. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  593. data/lib/hecks/runtime/registry/verification.rb +213 -227
  594. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  595. data/lib/hecks/runtime/registry.rb +156 -247
  596. data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
  597. data/lib/hecks/runtime/routing.rb +4 -15
  598. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  599. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  600. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  601. data/lib/hecks/runtime/tenant_check.rb +6 -68
  602. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  603. data/lib/hecks/runtime/value/admission.rb +16 -67
  604. data/lib/hecks/runtime/value/coercion.rb +162 -760
  605. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  606. data/lib/hecks/runtime/value/field_checks.rb +172 -0
  607. data/lib/hecks/runtime/value.rb +15 -84
  608. data/lib/hecks/runtime.rb +35 -69
  609. data/lib/hecks/rust_build/conformance.rb +158 -0
  610. data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
  611. data/lib/hecks/rust_build/coverage.rb +218 -0
  612. data/lib/hecks/rust_build/native_build.rb +124 -0
  613. data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
  614. data/lib/hecks/rust_build/project_rust.rb +332 -0
  615. data/lib/hecks/rust_build/wasm.rb +105 -0
  616. data/lib/hecks/rust_build/wasm_browser.rb +113 -0
  617. data/lib/hecks/rust_build.rb +144 -0
  618. data/lib/hecks/storehouse.rb +155 -582
  619. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
  620. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  621. data/lib/hecks/three_zero/forms.yml +127 -0
  622. data/lib/hecks/three_zero.rb +12 -0
  623. data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
  624. data/lib/hecks/tools/comment_style.rb +1070 -0
  625. data/lib/hecks/tools/corpus_report.rb +87 -0
  626. data/lib/hecks/tools/deploy_recipe.rb +255 -0
  627. data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
  628. data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
  629. data/lib/hecks/tools/era_projection_backfill.rb +94 -0
  630. data/lib/hecks/tools/era_reattest.rb +146 -0
  631. data/lib/hecks/tools/evolve_run.rb +189 -0
  632. data/lib/hecks/tools/fuzz_sweep.rb +373 -0
  633. data/lib/hecks/tools/heki_compaction.rb +100 -0
  634. data/lib/hecks/tools/hoist_local_givens.rb +246 -0
  635. data/lib/hecks/tools/journal_compaction.rb +89 -0
  636. data/lib/hecks/tools/oidc_manifests.rb +70 -0
  637. data/lib/hecks/tools/query_ir_run.rb +81 -0
  638. data/lib/hecks/tools/regeneration_run.rb +166 -0
  639. data/lib/hecks/tools/rust_comment_style.rb +642 -0
  640. data/lib/hecks/tools/sequence_script.rb +62 -0
  641. data/lib/hecks/tools/tail_merge.rb +117 -0
  642. data/lib/hecks/tools/tenant_provisioning.rb +142 -0
  643. data/lib/hecks/tools/translation_audit.rb +208 -0
  644. data/lib/hecks/tools/translation_scaffold.rb +131 -0
  645. data/lib/hecks/tools.rb +86 -0
  646. data/lib/hecks/vendoring/git_environment.rb +2 -8
  647. data/lib/hecks/vendoring/git_source.rb +4 -10
  648. data/lib/hecks/vendoring.rb +7 -46
  649. data/lib/hecks/version.rb +3 -14
  650. data/lib/hecks.rb +52 -90
  651. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  652. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  653. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  654. data/qa/settings.yml +66 -0
  655. data/rust/.cargo/config.toml +6 -0
  656. data/rust/.gitignore +2 -0
  657. data/rust/Cargo.lock +54 -0
  658. data/rust/Cargo.toml +61 -0
  659. data/rust/build/.cargo/config.toml +3 -0
  660. data/rust/build/.gitignore +1 -0
  661. data/rust/build/Cargo.lock +7 -0
  662. data/rust/build/Cargo.toml +19 -0
  663. data/rust/build/src/build_artifact.rs +47 -0
  664. data/rust/build/src/cargo_sync.rs +248 -0
  665. data/rust/build/src/json.rs +421 -0
  666. data/rust/build/src/lineage_pass.rs +285 -0
  667. data/rust/build/src/main.rs +51 -0
  668. data/rust/build/src/optional_pass.rs +150 -0
  669. data/rust/build/src/pipeline.rs +264 -0
  670. data/rust/build/src/reserved_names.rs +76 -0
  671. data/rust/build/src/resolve.rs +124 -0
  672. data/rust/build/src/root.rs +25 -0
  673. data/rust/build/src/sidecars.rs +73 -0
  674. data/rust/build/src/subprocess.rs +51 -0
  675. data/rust/build/src/tmp.rs +31 -0
  676. data/rust/codegen/.cargo/config.toml +3 -0
  677. data/rust/codegen/.gitignore +1 -0
  678. data/rust/codegen/Cargo.lock +7 -0
  679. data/rust/codegen/Cargo.toml +20 -0
  680. data/rust/codegen/src/attr.rs +32 -0
  681. data/rust/codegen/src/bridging.rs +481 -0
  682. data/rust/codegen/src/commands.rs +1226 -0
  683. data/rust/codegen/src/constraints.rs +109 -0
  684. data/rust/codegen/src/dependency_planning.rs +209 -0
  685. data/rust/codegen/src/domain_generator.rs +1288 -0
  686. data/rust/codegen/src/exemplar.rs +230 -0
  687. data/rust/codegen/src/expr_emitter.rs +87 -0
  688. data/rust/codegen/src/fielded.rs +192 -0
  689. data/rust/codegen/src/hecks_naming.rs +33 -0
  690. data/rust/codegen/src/json.rs +335 -0
  691. data/rust/codegen/src/json_codec.rs +697 -0
  692. data/rust/codegen/src/literal.rs +207 -0
  693. data/rust/codegen/src/main.rs +290 -0
  694. data/rust/codegen/src/manifest.rs +227 -0
  695. data/rust/codegen/src/mutations.rs +784 -0
  696. data/rust/codegen/src/naming.rs +286 -0
  697. data/rust/codegen/src/ports.rs +208 -0
  698. data/rust/codegen/src/prelude.rs +116 -0
  699. data/rust/codegen/src/queries.rs +786 -0
  700. data/rust/codegen/src/reactions.rs +532 -0
  701. data/rust/codegen/src/read_models.rs +697 -0
  702. data/rust/codegen/src/reference_specs.rs +40 -0
  703. data/rust/codegen/src/registry.rs +966 -0
  704. data/rust/codegen/src/reserved_names.rs +76 -0
  705. data/rust/codegen/src/shared.rs +93 -0
  706. data/rust/codegen/src/skip_reason.rs +25 -0
  707. data/rust/codegen/src/types.rs +362 -0
  708. data/rust/host/.cargo/config.toml +3 -0
  709. data/rust/host/.gitignore +1 -0
  710. data/rust/host/Cargo.lock +4297 -0
  711. data/rust/host/Cargo.toml +61 -0
  712. data/rust/host/HECKS_RELEASE +1 -0
  713. data/rust/host/rds-ca-bundle.pem +2736 -0
  714. data/rust/host/src/api.rs +1596 -0
  715. data/rust/host/src/approval.rs +652 -0
  716. data/rust/host/src/auth.rs +1287 -0
  717. data/rust/host/src/bin/expr_harness.rs +46 -0
  718. data/rust/host/src/bin/lineage_harness.rs +119 -0
  719. data/rust/host/src/bin/mint_harness.rs +135 -0
  720. data/rust/host/src/checkout.rs +265 -0
  721. data/rust/host/src/dispatch.rs +1443 -0
  722. data/rust/host/src/expr_json.rs +1117 -0
  723. data/rust/host/src/field_hints.rs +52 -0
  724. data/rust/host/src/ir.rs +733 -0
  725. data/rust/host/src/journal.rs +874 -0
  726. data/rust/host/src/lambda_client.rs +378 -0
  727. data/rust/host/src/log.rs +147 -0
  728. data/rust/host/src/main.rs +474 -0
  729. data/rust/host/src/mint.rs +1865 -0
  730. data/rust/host/src/payments/keystore.rs +330 -0
  731. data/rust/host/src/payments/tests.rs +1400 -0
  732. data/rust/host/src/payments.rs +767 -0
  733. data/rust/host/src/presentation.rs +698 -0
  734. data/rust/host/src/presentation_write.rs +1431 -0
  735. data/rust/host/src/query_step.rs +149 -0
  736. data/rust/host/src/rate_limit.rs +904 -0
  737. data/rust/host/src/reference_transform.rs +241 -0
  738. data/rust/host/src/reference_validate.rs +338 -0
  739. data/rust/host/src/resend.rs +296 -0
  740. data/rust/host/src/secrets.rs +106 -0
  741. data/rust/host/src/server.rs +663 -0
  742. data/rust/host/src/storage_shape.rs +175 -0
  743. data/rust/host/src/test_pg.rs +40 -0
  744. data/rust/host/src/ui_schema.rs +1351 -0
  745. data/rust/host/src/wasm_runner.rs +191 -0
  746. data/rust/host/src/web/newsletter/cooldown.rs +126 -0
  747. data/rust/host/src/web/newsletter/tests.rs +104 -0
  748. data/rust/host/src/web/newsletter.rs +310 -0
  749. data/rust/host/src/web/newsletter_send.rs +357 -0
  750. data/rust/host/src/web/registrations.rs +1505 -0
  751. data/rust/host/src/web.rs +2937 -0
  752. data/rust/lsp/.gitignore +1 -0
  753. data/rust/lsp/Cargo.lock +7 -0
  754. data/rust/lsp/Cargo.toml +16 -0
  755. data/rust/lsp/README.md +133 -0
  756. data/rust/lsp/src/diagnostics.rs +165 -0
  757. data/rust/lsp/src/json.rs +385 -0
  758. data/rust/lsp/src/main.rs +399 -0
  759. data/rust/lsp/src/outline.rs +177 -0
  760. data/rust/lsp/src/rpc.rs +67 -0
  761. data/rust/parser/.cargo/config.toml +5 -0
  762. data/rust/parser/.gitignore +1 -0
  763. data/rust/parser/Cargo.lock +7 -0
  764. data/rust/parser/Cargo.toml +21 -0
  765. data/rust/parser/src/build/closed_sets.rs +27 -0
  766. data/rust/parser/src/build/identity.rs +276 -0
  767. data/rust/parser/src/build/mod.rs +12 -0
  768. data/rust/parser/src/build/naming.rs +141 -0
  769. data/rust/parser/src/build/pattern_subset.rs +161 -0
  770. data/rust/parser/src/build/query_derive.rs +72 -0
  771. data/rust/parser/src/build/query_inference.rs +269 -0
  772. data/rust/parser/src/build/query_options.rs +100 -0
  773. data/rust/parser/src/build/read_model.rs +94 -0
  774. data/rust/parser/src/build/references.rs +32 -0
  775. data/rust/parser/src/canonical.rs +114 -0
  776. data/rust/parser/src/diag.rs +55 -0
  777. data/rust/parser/src/emit.rs +953 -0
  778. data/rust/parser/src/expr/ast_json.rs +147 -0
  779. data/rust/parser/src/expr/evaluator.rs +81 -0
  780. data/rust/parser/src/expr/mod.rs +84 -0
  781. data/rust/parser/src/expr/resolver.rs +497 -0
  782. data/rust/parser/src/ir.rs +387 -0
  783. data/rust/parser/src/keywords.rs +585 -0
  784. data/rust/parser/src/lex.rs +662 -0
  785. data/rust/parser/src/main.rs +252 -0
  786. data/rust/parser/src/parse/aggregate.rs +612 -0
  787. data/rust/parser/src/parse/chapter.rs +517 -0
  788. data/rust/parser/src/parse/command.rs +637 -0
  789. data/rust/parser/src/parse/domain_port.rs +127 -0
  790. data/rust/parser/src/parse/entity.rs +527 -0
  791. data/rust/parser/src/parse/file.rs +67 -0
  792. data/rust/parser/src/parse/hecksagon.rs +231 -0
  793. data/rust/parser/src/parse/lifecycle.rs +162 -0
  794. data/rust/parser/src/parse/mod.rs +1262 -0
  795. data/rust/parser/src/parse/policy.rs +87 -0
  796. data/rust/parser/src/parse/process_manager.rs +305 -0
  797. data/rust/parser/src/parse/query.rs +100 -0
  798. data/rust/parser/src/parse/read_model.rs +214 -0
  799. data/rust/parser/src/parse/value_object.rs +250 -0
  800. data/rust/parser/src/ruby_value.rs +422 -0
  801. data/rust/project/bridging.rb +257 -0
  802. data/rust/project/commands.rb +877 -0
  803. data/rust/project/constraints.rb +86 -0
  804. data/rust/project/dependency_planning.rb +178 -0
  805. data/rust/project/domain_generator.rb +980 -0
  806. data/rust/project/exemplar.rb +148 -0
  807. data/rust/project/expr_emitter.rb +72 -0
  808. data/rust/project/fielded.rb +141 -0
  809. data/rust/project/json_codec.rb +641 -0
  810. data/rust/project/mutations.rb +721 -0
  811. data/rust/project/naming.rb +205 -0
  812. data/rust/project/ports.rb +65 -0
  813. data/rust/project/queries.rb +493 -0
  814. data/rust/project/reactions.rb +317 -0
  815. data/rust/project/read_models.rb +690 -0
  816. data/rust/project/reference_specs.rb +27 -0
  817. data/rust/project/registry.rb +396 -0
  818. data/rust/project/skip_reason.rb +29 -0
  819. data/rust/project/types.rb +225 -0
  820. data/rust/project/write_if_changed.rb +83 -0
  821. data/rust/project.rb +30 -0
  822. data/rust/project_rust_pipeline.rb +383 -0
  823. data/rust/src/exemplar/commands.rs +279 -0
  824. data/rust/src/exemplar/constraints.rs +18 -0
  825. data/rust/src/exemplar/fielded.rs +280 -0
  826. data/rust/src/exemplar/json.rs +277 -0
  827. data/rust/src/exemplar/mod.rs +17 -0
  828. data/rust/src/exemplar/mutations.rs +80 -0
  829. data/rust/src/exemplar/queries.rs +33 -0
  830. data/rust/src/exemplar/reactions.rs +88 -0
  831. data/rust/src/exemplar/read_models.rs +48 -0
  832. data/rust/src/exemplar/registry.rs +166 -0
  833. data/rust/src/exemplar/types.rs +44 -0
  834. data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
  835. data/rust/src/kernel/attribute_shapes/list.rs +18 -0
  836. data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
  837. data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
  838. data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
  839. data/rust/src/kernel/cli.rs +585 -0
  840. data/rust/src/kernel/dispatch.rs +1090 -0
  841. data/rust/src/kernel/expr.rs +458 -0
  842. data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
  843. data/rust/src/kernel/expression_operators/comparison.rs +48 -0
  844. data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
  845. data/rust/src/kernel/expression_operators/logical.rs +13 -0
  846. data/rust/src/kernel/expression_operators/membership.rs +18 -0
  847. data/rust/src/kernel/expression_operators/mod.rs +68 -0
  848. data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
  849. data/rust/src/kernel/expression_operators/positional.rs +126 -0
  850. data/rust/src/kernel/expression_operators/presence.rs +101 -0
  851. data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
  852. data/rust/src/kernel/expression_operators/sized.rs +35 -0
  853. data/rust/src/kernel/expression_operators/text.rs +79 -0
  854. data/rust/src/kernel/expression_operators/to_string.rs +18 -0
  855. data/rust/src/kernel/json.rs +779 -0
  856. data/rust/src/kernel/mod.rs +133 -0
  857. data/rust/src/kernel/named_query.rs +219 -0
  858. data/rust/src/kernel/orchestrate.rs +1810 -0
  859. data/rust/src/kernel/pattern.rs +307 -0
  860. data/rust/src/kernel/query_comparators.rs +206 -0
  861. data/rust/src/kernel/query_ordering.rs +103 -0
  862. data/rust/src/kernel/read_model.rs +914 -0
  863. data/rust/src/kernel/reference_lookup.rs +149 -0
  864. data/rust/src/kernel/repository.rs +468 -0
  865. data/rust/src/kernel/routing.rs +612 -0
  866. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
  867. data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
  868. data/rust/src/kernel/vocab/field_hint.rs +70 -0
  869. data/rust/src/kernel/vocab/mod.rs +20 -0
  870. data/rust/src/kernel/vocab/query_comparator.rs +65 -0
  871. data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
  872. data/rust/src/lib.rs +8 -0
  873. data/rust/src/main.rs +16 -0
  874. data/rust/web/.gitignore +1 -0
  875. data/rust/web/Cargo.lock +119 -0
  876. data/rust/web/Cargo.toml +18 -0
  877. data/rust/web/src/lib.rs +8 -0
  878. metadata +478 -12
  879. data/lib/hecks/facade/cli_door.rb +0 -178
  880. data/lib/hecks/facade/cli_runner.rb +0 -271
  881. data/lib/hecks/facade/handle.rb +0 -293
  882. data/lib/hecks/facade/json_door.rb +0 -247
  883. data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
  884. data/lib/hecks/facade/surface/chapter.rb +0 -116
  885. data/lib/hecks/facade/surface.rb +0 -61
  886. data/lib/hecks/mcp_door_scope.rb +0 -176
@@ -1,37 +1,14 @@
1
1
  module Hecks
2
- # Reopened here purely to require in every driven adapter under
3
- # adapters/driven/ below (see the comment inside for what "driven side"
4
- # means) — the actual namespace is declared in adapters.rb.
2
+ # The driven side: every store or reader an adapter declaration can bind.
5
3
  module Adapters
6
- # The driven side — every store or reader an adapter declaration can
7
- # bind. A small adapter is one file beside this one; sqlite, postgres
8
- # and heki keep a directory for their supporting cast. Each `.adapter`
9
- # file alongside is the DSL declaration the grammar bootstrap and the
10
- # Folder adapter load as data.
11
4
  end
12
5
  end
13
6
 
14
7
  require_relative "driven/memory"
15
8
  require_relative "driven/sqlite"
16
9
  require_relative "driven/postgres"
17
- # `PostgresEra` is not `require_relative`d here — ADR 0033 moved it, and
18
- # the rest of the era/lineage/translation subsystem, behind a loadable
19
- # persistence plugin (`hecks/ports/persistence/plugins/era`) rather than
20
- # requiring every app to carry it whether or not anything ever binds
21
- # `persisted_by "PostgresEra"`. `Module#autoload` is the one-line seam
22
- # that makes that genuinely load-nothing-until-asked instead of pushing
23
- # an explicit `require` onto every one of the ~15 generic `bin/*` tools
24
- # that boot an arbitrary checked-in domain (several of which — pizzas,
25
- # compliance, chess, roster — bind PostgresEra): the first real
26
- # `Adapters.const_get("PostgresEra")` (`registry/verification.rb`'s own
27
- # adapter resolution, unchanged) transparently `require`s the plugin
28
- # entry point, which defines the constant and calls `register_plugin`
29
- # as its own side effect (`plugins/era.rb`'s last line) — the exact
30
- # same effect an explicit `require "hecks/ports/persistence/plugins/
31
- # era"` has, just deferred to the moment something is actually asked
32
- # for `PostgresEra` rather than sprinkled across every caller that
33
- # might. A domain that never binds it never triggers the autoload, so
34
- # never loads a line of era code — unchanged from ADR 0033's own goal.
10
+ # PostgresEra lives in a persistence plugin, autoloaded so a domain that never binds
11
+ # it loads no era code; the plugin entry point registers itself on load (ADR 0033).
35
12
  Hecks::Adapters.autoload(:PostgresEra, "hecks/ports/persistence/plugins/era")
36
13
  require_relative "driven/lambda"
37
14
  require_relative "driven/heki"
@@ -44,16 +21,8 @@ require_relative "driven/tenant_provisioner"
44
21
  require_relative "driven/secure_random_identity"
45
22
  require_relative "driven/in_process_key_vault"
46
23
  require_relative "driven/system_clock"
47
- # `SequentialIdentity` — the deterministic identity_generation test
48
- # double — is not required here on purpose. It lives at
49
- # spec/fixtures/sequential_identity.{adapter,rb}, loaded explicitly by
50
- # whichever spec wants it: this file's `require_relative` list is what
51
- # `Folder#load_library`'s `.adapter` glob backs, and `.adapter` DSL
52
- # declarations register into every registry any real `Hecks.boot` ever
53
- # builds. Two adapters answering `identity_generation` unconditionally
54
- # would make the port permanently ambiguous — `Ports::IdentityGeneration
55
- # .adapter` refuses to choose between more than one — for every
56
- # consumer, forever, not just specs that want the deterministic one.
24
+ # SequentialIdentity (spec/fixtures) is deliberately not required here: a second
25
+ # `identity_generation` adapter would make that port ambiguous for every boot.
57
26
  require_relative "driven/governance_authorization"
58
27
  require_relative "driven/identity_registry"
59
28
  require_relative "driven/google_authentication"
@@ -4,85 +4,23 @@ require "rack"
4
4
 
5
5
  module Hecks
6
6
  module Adapters
7
- # **The driving side** — code an outside caller reaches in through,
8
- # rather than code the domain reaches out through. Every existing
9
- # file under `adapters/driven/` is the latter: a store or reader a
10
- # `persisted_by`/`port` binding resolves to, called by this
11
- # framework's own runtime. Nothing under this repository has ever
12
- # been the mirror image before — code that receives a request from
13
- # the outside world and turns it into a dispatch — so this is the
14
- # first entry, and the directory itself is new.
7
+ # Driving adapters: code an outside caller reaches in through.
15
8
  module Driving
16
- # **A GitHub webhook receiver, transport only** — the same split
17
- # `Hecks::Adapters::GithubChecks` (qa/adapters/github_checks.rb,
18
- # this class's own pull-side sibling) already draws for itself:
19
- # this file owns proving a request really came from GitHub and
20
- # unwrapping GitHub's own webhook envelope (`X-GitHub-Event`, the
21
- # JSON body, GitHub's own automatic `ping` check) — never which
22
- # commands to dispatch about what it finds inside. That is exactly
23
- # as domain-specific as `GithubChecks#run` turning `check-runs`
24
- # JSON into green-or-raise, and lives exactly where that class's
25
- # own header explains such logic belongs: outside this library,
26
- # in `qa/adapters/github_ci_webhook.rb`, the subclass of this file
27
- # that actually knows what a `QualityControl::Clearance` is.
9
+ # A GitHub webhook receiver, transport only: a rack app that verifies the signature.
10
+ # A subclass implements `#handle_event(event, action, payload)` returning `[status, body]`.
28
11
  #
29
- # ## A plain rack app
30
- #
31
- # A plain rack app (`#call(env)`) — no Sinatra, no Rails — the same
32
- # shape `Hecks::Forms::App` (lib/hecks/forms/app.rb) already
33
- # established for the one other HTTP-facing surface this library
34
- # ships. `rack` is a lazy Gemfile dependency for exactly the reason
35
- # that file's own header gives: this file is never required by
36
- # `require "hecks"` (nothing under `adapters.rb`'s own eager
37
- # `adapters/driven` load names it — see that file's own header),
38
- # so a project that never mounts a driving adapter never needs
39
- # `rack` installed, the same "opt in by requiring the file at all"
40
- # contract `hecks/forms.rb` already has for `Forms::App`.
41
- #
42
- # ## Subclass responsibility
43
- #
44
- # Implement `#handle_event(event, action,
45
- # payload)`, returning `[http_status, response_body_hash]`. Called
46
- # only after the signature has verified and the body has parsed as
47
- # JSON — a subclass never has to re-check either. `event` is
48
- # GitHub's own `X-GitHub-Event` header value ("check_suite",
49
- # "check_run", "pull_request", ...); `action` is the payload's own
50
- # top-level `"action"` field when it has one (GitHub's webhooks
51
- # nearly all carry one — "completed", "requested", "opened", ...)
52
- # and nil when it does not. `ping` — GitHub's own automatic
53
- # connectivity check, sent once when a webhook is first saved in
54
- # repository settings — is answered here and never reaches a
55
- # subclass at all; there is nothing domain-specific to decide
56
- # about it.
12
+ # Not required by `require "hecks"`, so `rack` stays an opt-in dependency.
57
13
  class GithubWebhook
58
- # **Refused, loudly** — the same shape a domain refusal already takes
59
- # everywhere else in this codebase (`Runtime::DOMAIN_REFUSALS`,
60
- # `Forms::App`'s own `{error:, message:}` JSON body for a bad
61
- # command). A request that cannot prove it came from GitHub gets
62
- # a real 401 and a named reason, never a silent 200 that would
63
- # let a forged "CI passed" payload regress nothing while looking
64
- # exactly like success in a log nobody re-reads.
14
+ # Raised for a request that cannot prove it came from GitHub; answered with a 401.
65
15
  class InvalidSignature < StandardError; end
66
16
 
67
- # **The body did not even parse** — distinct from a signature refusal:
68
- # this body genuinely came from whoever signed it (checked
69
- # first, before parsing ever runs — see `#call`), and simply
70
- # is not JSON. Still refused, never guessed at.
17
+ # Raised when a correctly signed body is not JSON; answered with a 400.
71
18
  class MalformedPayload < StandardError; end
72
19
 
73
20
  SIGNATURE_HEADER = "HTTP_X_HUB_SIGNATURE_256".freeze
74
21
  EVENT_HEADER = "HTTP_X_GITHUB_EVENT".freeze
75
22
 
76
- # `secret:` has no default, on purpose — the same rule
77
- # `GoogleAuthentication`'s own header states for its own
78
- # `ENV.fetch`, restated here because the consequence is worse for
79
- # a webhook: an unverified signature check is not "half
80
- # configured", it is no verification at all, silently accepting
81
- # anything claiming to be GitHub. A caller passes the real
82
- # secret explicitly — from `ENV.fetch("GITHUB_WEBHOOK_SECRET")`
83
- # or wherever it keeps one — rather than this class reaching into
84
- # the environment itself and hiding that requirement inside a
85
- # default.
23
+ # `secret:` has no default: a missing secret would silently disable verification.
86
24
  # @param secret [String] the shared webhook secret (e.g. `ENV.fetch
87
25
  # ("GITHUB_WEBHOOK_SECRET")`), checked against each request's `X-Hub-Signature-256`
88
26
  # @raise [ArgumentError] if `secret` is nil or empty
@@ -120,13 +58,7 @@ module Hecks
120
58
 
121
59
  private
122
60
 
123
- # Constant-time compare, not `==`. A byte-by-byte `==` returns
124
- # the moment it finds the first mismatching byte, so how long
125
- # that took leaks how many leading bytes of a forged signature
126
- # were already right to anyone timing the response — GitHub's
127
- # own webhook documentation calls this out by name and recommends
128
- # exactly the constant-time compare `Rack::Utils.secure_compare`
129
- # already gives for free, reused rather than hand-rolled.
61
+ # Constant-time compare: `==` leaks how many leading bytes of a forged signature matched.
130
62
  def verify_signature!(request, body)
131
63
  header = request.get_header(SIGNATURE_HEADER)
132
64
  raise InvalidSignature, "missing #{SIGNATURE_HEADER.sub('HTTP_', '').tr('_', '-')} header" if header.to_s.empty?
@@ -1,20 +1,12 @@
1
1
  require_relative "ir"
2
2
 
3
- # The authoring surface for `Hecks.behaviors "Name" do ... end` — one
4
- # `test "description" do ... end` block per case, `tests`/`setup`/`input`/
5
- # `expect` inside. `instance_eval`-based, the same shape every other
6
- # hecks DSL builder uses (`WorldBuilder`, `HecksagonBuilder`).
3
+ # The authoring surface for `Hecks.behaviors "Name" do ... end`, built with `instance_eval`.
7
4
  module Hecks
8
5
  module Behaviors
9
- # Raised at `Hecks.behaviors` build time — a missing `vision` or
10
- # `loads` line names the fix directly rather than failing later, deep
11
- # inside a boot, over a suite that was never going to be scoped.
6
+ # Raised at build time, so a missing `vision` or `loads` fails with the fix named.
12
7
  class Malformed < StandardError; end
13
8
 
14
- # The `test "description" do ... end` block's own receiver — collects
15
- # `tests`/`setup`/`input`/`expect` calls and builds a `TestCase` (ir.rb).
16
- # `validate_expect!` (private, below) is where a malformed or empty
17
- # `expect` is refused at build time rather than silently passing later.
9
+ # The `test "description" do ... end` receiver; builds a `TestCase` (ir.rb).
18
10
  class TestCaseBuilder
19
11
  # @param description [String] the `test "description" do ... end` text
20
12
  def initialize(description)
@@ -82,14 +74,8 @@ module Hecks
82
74
 
83
75
  private
84
76
 
85
- # Closes the silent-pass paths a free-form `expect(**kwargs)` merge
86
- # otherwise leaves open: a test with no `expect` at all asserts
87
- # nothing and passes whenever dispatch doesn't raise; `count:` on a
88
- # command and `emits:` on a query are each read by neither runner
89
- # (Expectations#run_command/#run_query), so they're accepted here
90
- # and then silently ignored at run time. Checking both at build
91
- # time, not in the runners, makes them errors on the file that
92
- # wrote them rather than green checks nobody questions.
77
+ # Refuses expectations that would pass silently: an empty `expect`, `count:` on a command,
78
+ # or `emits:` on a query (neither runner reads those). Checked at build time.
93
79
  def validate_expect!
94
80
  if @expect.empty?
95
81
  raise Malformed, "test #{@description.inspect} has no `expect` — say what this " \
@@ -108,9 +94,7 @@ module Hecks
108
94
  end
109
95
  end
110
96
 
111
- # The top-level `Hecks.behaviors "Name" do ... end` receiver — collects
112
- # `vision`/`loads`/`test` calls and builds a `BehaviorsSuite` (ir.rb),
113
- # refusing to build one missing either `vision` or `loads` (`#build`).
97
+ # The top-level `Hecks.behaviors` receiver; builds a `BehaviorsSuite` (ir.rb).
114
98
  class BehaviorsBuilder
115
99
  # @param name [String] the suite's declared name
116
100
  # @param source_path [String] the `.behaviors` file's own path
@@ -129,9 +113,7 @@ module Hecks
129
113
  # @return [String] `text`, unchanged
130
114
  def vision(text) = @vision = text
131
115
 
132
- # Relative to this `.behaviors` file, never to the filesystem's cwd
133
- # or a same-stem convention — scope is a fact this file declares,
134
- # not one a runner infers.
116
+ # Paths are relative to this `.behaviors` file, never the cwd.
135
117
  #
136
118
  # @param paths [Array<String>] paths to the files this suite's domain boots
137
119
  # from, relative to the `.behaviors` file
@@ -5,45 +5,11 @@ require_relative "../runtime/value"
5
5
  require_relative "../runtime/reaction_invocation"
6
6
  require_relative "../ports/persistence/binding_policy"
7
7
 
8
- # Hecks::Behaviors::Expectations
9
- #
10
- # ## What it does
11
- #
12
- # One test case, start to finish: take the suite's own runtime (booted
13
- # once for exactly what its `loads` names, reset to nothing between
14
- # tests — `runtime_for`), replay `setup` dispatches, dispatch (or query)
15
- # the command under test, check `expect`. Split out of
16
- # runner.rb the same way the file-count/sweep concern is split from a
17
- # single test's own execution.
18
- #
19
- # ## Deviations from a prior port
20
- #
21
- # Two deliberate deviations from a prior port of this same idea (read
22
- # before writing this, not reinvented):
23
- #
24
- # 1. A `setup` refusal and a refusal from the command under test are
25
- # caught in separate rescue scopes. The prior port wrapped the whole
26
- # test body — setups included — in one `rescue *REFUSAL_CLASSES`, so a
27
- # broken setup could spuriously satisfy `expect refused: "..."` if its
28
- # own refusal happened to match the expected substring. Here, any
29
- # domain refusal during `setup` is unconditionally an error — the
30
- # example never got to the situation it claims to test.
31
- #
32
- # 2. `emits:` is read off a `registry.event_log` diff around the tested
33
- # dispatch, not off `Result#events` alone. `Result#events` only holds
34
- # the events the outermost dispatch announced; a policy's own cascade
35
- # reenters through the same `Dispatcher#dispatch` (`PolicyInterpreter
36
- # #deliver` → `door.reenter` → `dispatch`), and every dispatch's
37
- # events — outer and reentrant alike — land in the one shared
38
- # `registry.event_log`, in order (`CommandRules::Emission#emit`,
39
- # `PortOperationInterpreter#emit`/`#call`). Diffing that log's length
40
- # before/after the tested dispatch is the one read that actually sees
41
- # a cascade — this DSL has no `kind: :cascade` because cascades are
42
- # always on and `emits:` is expected to see them.
8
+ # Runs one behaviors test case: replays its setup dispatches, dispatches (or
9
+ # queries) the command under test, and checks the result against `expect`.
43
10
  module Hecks
44
11
  module Behaviors
45
- # See this file's own header above for what this module does and the
46
- # two deliberate deviations from the prior port it's built from.
12
+ # Runs one behaviors test case: replays its setup, dispatches the command, checks `expect`.
47
13
  module Expectations
48
14
  module_function
49
15
 
@@ -66,6 +32,8 @@ module Hecks
66
32
 
67
33
  current_setup = nil
68
34
  begin
35
+ # Caught separately from the tested command's own refusal, so a broken
36
+ # setup can't spuriously satisfy `expect refused: "..."` by coincidence.
69
37
  test.setups.each do |setup|
70
38
  current_setup = setup
71
39
  dispatch_command(runtime, qualify(setup.command, nil, bluebooks, kind: :command), setup.args)
@@ -79,20 +47,9 @@ module Hecks
79
47
  error_result(test, "#{e.class}: #{e.message}")
80
48
  end
81
49
 
82
- # One boot per suite, not per test. The isolation a test needs is a
83
- # runtime with nothing in it — and a boot of the same files gives
84
- # exactly that back for the price of `Registry#reset_runtime_state!`
85
- # instead of ~2s of loading, verifying and era-checking the same
86
- # bluebook again (chess: 76 behaviours, 155s of which was booting
87
- # `chess.bluebook` 76 times). Keyed by the suite's own `loads` and
88
- # their mtimes, so an edited bluebook boots fresh on the next test
89
- # rather than running against a stale one — the property a watch
90
- # loop or a long rspec session actually relies on. `runtime:` lets
91
- # a caller that already holds a booted runtime (a spec, a REPL)
92
- # hand it in; it is reset the same way.
93
- # Not frozen — a real cache, mutated below (`RUNTIMES[key] ||=
94
- # boot_and_guard(files)`) and by #reset!. False positive for
95
- # Style/MutableConstant.
50
+ # Cached per suite, keyed by `loads`' file paths and mtimes, so a boot is
51
+ # reused across tests but an edited bluebook boots fresh on the next one.
52
+ # Mutated in place (`RUNTIMES[key] ||= boot_and_guard(files)`, and #reset!).
96
53
  # rubocop:disable-next Style/MutableConstant
97
54
  RUNTIMES = {}
98
55
  RUNTIMES_LOCK = Mutex.new
@@ -115,16 +72,8 @@ module Hecks
115
72
  end
116
73
  end
117
74
 
118
- # `reset_runtime_state!` only drops repository objects between
119
- # tests (registry.rb) — sufficient isolation for `Memory`, whose
120
- # `@records` is a plain per-instance ivar, so a fresh object really
121
- # is a fresh store. Against anything else (Sqlite, Postgres) the
122
- # rows themselves stay put: tests leak into each other, and a
123
- # suite booted against a domain's real hecksagon writes to a real
124
- # database. Refusing that wiring here, at boot, is the same shape
125
- # of guard `BindingPolicy` already applies to a missing bind — the
126
- # project's identity is refusing bad wiring up front, not
127
- # discovering it mid-suite.
75
+ # Refuses at boot when any aggregate binds to a non-Memory adapter —
76
+ # `reset_runtime_state!` only resets Memory's own per-instance store.
128
77
  #
129
78
  # @param files [Array<String>] absolute paths to the bluebook/hecksagon/world
130
79
  # files to boot
@@ -132,7 +81,7 @@ module Hecks
132
81
  # Memory-only-guarded runtime
133
82
  # @raise [Malformed] if any aggregate is bound to a non-Memory adapter
134
83
  def boot_and_guard(files)
135
- runtime = Hecks::Runtime::Loader.boot_files(files, install_facade: false)
84
+ runtime = Hecks::Runtime::Loader.boot_files(files, install_doors: false)
136
85
  guard_memory_only!(runtime)
137
86
  runtime
138
87
  end
@@ -209,17 +158,8 @@ module Hecks
209
158
  check_ok(test) || check_fields(test, settled_state(runtime, verb, result)) || pass_result(test)
210
159
  end
211
160
 
212
- # A field expectation reads the aggregate as it stands once the
213
- # dispatch and its whole cascade have run — the same "cascades are
214
- # always on" reading `emits:` already commits to. `Result#state` is
215
- # the wrong source for that: it snapshots the instance the outer
216
- # dispatch saved, and a policy's own reentrant dispatch (a ply
217
- # advancing off a Moved event, a move count bumping) hydrates and
218
- # saves a fresh record afterward — so a field the cascade wrote
219
- # read back stale (found live: `expect move_count: 1` got 0 while
220
- # `emits:` saw MoveCountBumped in the same test). The repository
221
- # holds the settled record; read it back by the id the dispatch
222
- # itself answered with.
161
+ # Reads the aggregate back from the repository, not `Result#state` — a
162
+ # policy's own reentrant dispatch can re-save the record afterward.
223
163
  #
224
164
  # @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the suite's
225
165
  # booted runtime
@@ -241,44 +181,15 @@ module Hecks
241
181
  record ? record.state : (result.state || {})
242
182
  end
243
183
 
244
- # A behaviors test writes a dispatch the way the guide's own chess
245
- # examples do — receiver identity and command facts side by side
246
- # (`label: "g", id: "wn", to: { file: 2, rank: 2 }`) — and since
247
- # #335 the dispatcher's own `to:` keyword is the routing envelope,
248
- # so forwarding those kwargs loose collides the moment a domain
249
- # declares a command fact named `to` (chess does: every Move's own
250
- # destination). Found live: every such test failed with "to: does
251
- # not recognize file, rank" while this guide promised the spelling
252
- # works. `ReactionInvocation.build` is #335's own seam for turning
253
- # mixed facts into the strict envelope — identities lifted into
254
- # `to:`, declared facts into `with:` — so a behaviors dispatch now
255
- # goes through the exact same separation a policy's projection
256
- # does. A verb that names a port operation (checked explicitly,
257
- # below — "Pizzas::Order.PaymentGateway.Receive") keeps the loose
258
- # passthrough instead: its own input already spells the port
259
- # form's `to:`/`with:`, which the dispatcher's port branch reads
260
- # directly, and `ReactionInvocation.build`'s explicit envelope
261
- # expects a command's own declared attributes at the top level,
262
- # not a port operation's already-wrapped `to:`/`with:` shape.
184
+ # Splits a mixed dispatch (receiver identity plus declared facts, e.g.
185
+ # `to: { file: 2, rank: 2 }`) into the dispatcher's strict `to:`/`with:` envelope.
263
186
  #
264
- # Checks for a port operation directly rather than leaning on
265
- # `resolve_target` to raise `UnknownVerb` for one — a refusal that held
266
- # only so long as nothing else ever asked it to resolve a port-operation
267
- # verb. Now that a `policy` can legitimately `trigger` a port operation
268
- # (`ReactionInvocation#resolve_target`'s own port-operation branch),
269
- # that raise does not happen, so this checks directly instead.
270
- #
271
- # @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the suite's
272
- # booted runtime
187
+ # @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the suite's booted runtime
273
188
  # @param verb [String] the command's dotted FQN, or a port operation's
274
- # @param args [Hash{Symbol => Object}] the command's (or setup's) facts, mixing
275
- # receiver identity and declared arguments
276
- # @return [Runtime::Dispatcher::Result, Runtime::RemoteDispatcher::Result] the
277
- # dispatch's own result
278
- # @raise [Runtime::UnknownVerb] if `verb` is not fully qualified or names an
279
- # undeclared domain, aggregate, command, entity or port operation
280
- # @raise [StandardError] any class in `Runtime::DOMAIN_REFUSALS` when the
281
- # domain refuses the call
189
+ # @param args [Hash{Symbol => Object}] the facts, mixing identity and declared arguments
190
+ # @return [Runtime::Dispatcher::Result, Runtime::RemoteDispatcher::Result] the dispatch result
191
+ # @raise [Runtime::UnknownVerb] if `verb` names an undeclared construct
192
+ # @raise [StandardError] any `Runtime::DOMAIN_REFUSALS` class, when the domain refuses
282
193
  def dispatch_command(runtime, verb, args)
283
194
  return runtime.dispatch_flat(verb, args) if port_operation?(runtime, verb)
284
195
 
@@ -297,10 +208,8 @@ module Hecks
297
208
  end
298
209
  end
299
210
 
300
- # The same "Head.Rest" shape `Dispatcher#dispatch` and
301
- # `ReactionInvocation#resolve_target` both already check — a bare
302
- # domain/aggregate lookup plus a port-name lookup, no command
303
- # resolution needed since all this asks is whether one exists.
211
+ # The same "Head.Rest" split `Dispatcher#dispatch` already uses — just a
212
+ # domain/aggregate and port-name lookup, no command resolution needed.
304
213
  #
305
214
  # @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the suite's
306
215
  # booted runtime
@@ -358,12 +267,8 @@ module Hecks
358
267
  test.expect.keys.any? { |key| !SPECIAL_KEYS.include?(key) }
359
268
  end
360
269
 
361
- # A field expectation on a query names one row's shape, so it only
362
- # makes sense once the query has settled on exactly one — the same
363
- # reason `expect status: "sold"` on a multi-row answer would be
364
- # ambiguous about which row it's describing. `check_fields` itself
365
- # stays row-shaped (it already is, for `run_command`'s settled
366
- # state); this picks which row it reads.
270
+ # A field expectation on a query only makes sense once it has settled on
271
+ # exactly one row; this picks that row (or fails naming the row count).
367
272
  #
368
273
  # @param test [Behaviors::TestCase] the test case, for the fail message
369
274
  # @param rows [Array<Hash>, Hash] the query's own result
@@ -437,12 +342,8 @@ module Hecks
437
342
  fail_result(test, "expected refused: #{expected.inspect}, got #{msg.inspect}")
438
343
  end
439
344
 
440
- # The real corpus this DSL is proven against writes VO-typed
441
- # `expect` values both ways — bare (`expect kind: "bishop"`) and
442
- # wrapped (`expect kind: { value: "bishop" }`). A live record's
443
- # field always comes back as a `Hecks::Runtime::Value`;
444
- # normalizing both sides to the same bare-scalar-or-plain-hash
445
- # shape is the one comparison that accepts either spelling.
345
+ # Normalizes both `expect` spellings (bare or `{value: ...}`) and a live
346
+ # `Hecks::Runtime::Value` field to the same bare-scalar-or-plain-hash shape.
446
347
  #
447
348
  # @param value [Object] a stored field's value, or an `expect` value to compare
448
349
  # it against
@@ -455,13 +356,8 @@ module Hecks
455
356
  value
456
357
  end
457
358
 
458
- # A bare `tests`/`setup` command name carries no domain — `loads`
459
- # can name more than one bluebook, so resolution searches every
460
- # aggregate across every bluebook the suite booted for the one that
461
- # actually declares the command. `on:` (when given, only ever on
462
- # the tested command — `setup` never receives it, see the DSL
463
- # contract) narrows the search to one aggregate by name instead of
464
- # searching all of them.
359
+ # Searches every aggregate of every bluebook the suite booted for the one
360
+ # declaring `command`; `on:` narrows the search to one aggregate by name.
465
361
  #
466
362
  # @param command [String, Symbol] a bare verb, or an already-dotted FQN
467
363
  # @param on_aggregate [String, Symbol, nil] the aggregate to search, or nil to
@@ -478,11 +374,8 @@ module Hecks
478
374
  disambiguate_qualified_name(candidates, command, kind, bluebooks)
479
375
  end
480
376
 
481
- # Finds every aggregate that could be what a bare command/query name refers to.
482
- #
483
- # **The search** — every (bluebook, aggregate) pair that declares a
484
- # command/query named `command`, narrowed to `on_aggregate` by name
485
- # when given.
377
+ # Finds every (bluebook, aggregate) pair that declares a command/query
378
+ # named `command`, narrowed to `on_aggregate` by name when given.
486
379
  #
487
380
  # @param command [String, Symbol] the bare verb to search for
488
381
  # @param on_aggregate [String, Symbol, nil] the aggregate to search, or nil to
@@ -502,11 +395,8 @@ module Hecks
502
395
  pairs.select { |_, agg| agg.public_send(members).any? { |m| m.hecks_name == command.to_s } }
503
396
  end
504
397
 
505
- # Resolves a search's candidates to exactly one dotted FQN, or refuses.
506
- #
507
- # **The report** — zero candidates and more-than-one candidates both
508
- # refuse (with a different message); exactly one resolves to its
509
- # dotted FQN.
398
+ # Resolves a search's candidates to exactly one dotted FQN; zero or more
399
+ # than one both refuse, each with a different message.
510
400
  #
511
401
  # @param candidates [Array<Array(Bluebook::Chapter, Bluebook::Aggregate)>] the
512
402
  # matching (chapter, aggregate) pairs found by `qualify_candidates`
@@ -1,29 +1,17 @@
1
1
  # Hecks::Behaviors::{TestSetup,TestCase,BehaviorsSuite}
2
2
  #
3
- # The `.behaviors` authoring surface's own IR — plain Structs, holding
4
- # exactly what `Hecks.behaviors "Name" do ... end` collected. Deliberately
5
- # not part of `Hecks::IR`/`emits_ir` — a behaviors suite is never
6
- # collected into a domain Registry (see `Hecks.behaviors`), never
7
- # dispatched through MetaValidator, and carries none of the self-hosted
8
- # round-trip machinery a real bluebook construct does. It is a test
9
- # artifact a runner reads on demand, not a domain a boot needs.
3
+ # Plain Structs holding what `Hecks.behaviors "Name" do ... end` collected; a suite is never
4
+ # collected into a domain Registry.
10
5
  module Hecks
11
- # The `.behaviors` toolkit: the DSL a `.behaviors` file is written against
12
- # (`Hecks.behaviors`, dsl.rb), the plain-Struct IR it builds (this file), the runner
13
- # that boots a suite's domain and checks each test (runner.rb, expectations.rb), and
14
- # an rspec shim for a consuming app's own suite (rspec.rb).
6
+ # The `.behaviors` toolkit: DSL, IR, runner and rspec shim.
15
7
  module Behaviors
16
8
  TestSetup = Struct.new(:command, :args, keyword_init: true)
17
9
 
18
10
  TestCase = Struct.new(:description, :tests_command, :on_aggregate, :kind,
19
11
  :setups, :input, :expect, keyword_init: true) do
20
- # Tells whether `tests_command` is already a fully qualified verb name.
12
+ # Whether `tests_command` is already a fully qualified verb name.
21
13
  #
22
- # An already-dotted tests_command is a literal FQN; otherwise `on:`
23
- # composes with the domain name resolved once setups/the tested
24
- # dispatch actually run (see Expectations — the domain isn't known
25
- # until `loads` is booted, so it's a runtime concern, not a field
26
- # here).
14
+ # @return [Boolean] true when `tests_command` contains a `.`
27
15
  #
28
16
  # @return [Boolean] true when `tests_command` contains a `.`
29
17
  def dotted? = tests_command.to_s.include?(".")
@@ -34,9 +22,8 @@ module Hecks
34
22
  def query? = kind == :query
35
23
  end
36
24
 
37
- # `loads` — absolute paths, already resolved against the `.behaviors`
38
- # file's own directory by the DSL (`BehaviorsBuilder#loads`). `path` is
39
- # the `.behaviors` file itself, kept for error messages.
25
+ # `loads` holds absolute paths resolved against the `.behaviors` file's directory;
26
+ # `path` is that file, kept for error messages.
40
27
  BehaviorsSuite = Struct.new(:name, :vision, :loads, :tests, :path, keyword_init: true)
41
28
  end
42
29
  end
@@ -1,13 +1,8 @@
1
1
  require_relative "../behaviors"
2
2
 
3
- # Hecks::Behaviors::RSpec.describe_file(path) — the shim a consumer's
4
- # `bundle exec rspec` uses to run `.behaviors` files as ordinary examples,
5
- # one `it` per test, named by the test's own description string. Same
6
- # shape `spec/guides_spec.rb` uses for doctested guides: the file is
7
- # parsed at collection time (cheap — `Behaviors.parse`, no test actually
8
- # run yet, just enough to know the `it` names), and each test's own
9
- # `Expectations.run_one` runs lazily inside its own `it`, exactly when
10
- # rspec actually executes it.
3
+ # Hecks::Behaviors::RSpec.describe_file(path) registers one `it` per test in a `.behaviors` file,
4
+ # so a consumer's `bundle exec rspec` runs it. The file is parsed at collection time; each test
5
+ # runs lazily inside its own `it`.
11
6
  #
12
7
  # require "hecks/behaviors/rspec"
13
8
  #
@@ -16,19 +11,13 @@ require_relative "../behaviors"
16
11
  # end
17
12
  module Hecks
18
13
  module Behaviors
19
- # See this file's own header above for what `describe_file` does and
20
- # how a consumer wires it into their own `bundle exec rspec` run.
14
+ # Registers one example per test in a `.behaviors` file so a consumer's suite runs it.
21
15
  module RSpec
22
16
  module_function
23
17
 
24
- # Parses one `.behaviors` file and registers an rspec example group for it, one
25
- # `it` per test named by the test's own description.
18
+ # Registers an rspec example group for one `.behaviors` file, one `it` per test.
26
19
  #
27
- # @param path [String] the `.behaviors` file's path
28
- # @return [void]
29
- # @raise [RuntimeError] not raised by this call itself; wraps `parsed.parse_error`'s
30
- # message and is raised only when rspec later runs the generated "loads without a
31
- # parse error" example, so it surfaces as that example's failure
20
+ # A parse error surfaces as a failing "loads without a parse error" example.
32
21
  def describe_file(path)
33
22
  parsed = Behaviors.parse(path)
34
23