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,60 +1,13 @@
1
1
  module Hecks
2
- # A named registry of "canonical IR in, external artifact out" tools —
3
- # §30 of docs/HECKS_IMPLEMENTATION_PLAN.md. Before this existed, every
4
- # such tool was its own thing with its own call shape: `Exporter`
5
- # (registry-wide, consumed directly by bin/ir, bin/project_rust, and
6
- # translation/audit's approval digest — untouched by this file, still
7
- # exactly what those three read), and `RustProjection::Projector`
8
- # (`rust/project.rb`, a whole separate Ruby program under a
9
- # confusingly-identical module name) are the two that already exist.
10
- # Neither is registered here — retrofitting either is real, separate
11
- # work (Rust's generator is a whole second toolchain; a UL/OIDC
12
- # projector doesn't exist yet at all) — but `:ir` is, as a genuine,
13
- # working, golden-tested example of the shape every future projector
14
- # (`:rust`, `:ul`, `:openid`, ...) is meant to follow.
2
+ # A named registry of "canonical IR in, external artifact out" tools, each
3
+ # taking one bluebook's IR and answering a derived artifact (`:ir`, `:docs`, ...).
15
4
  #
16
- # The unit is one bluebook's IR, not a whole booted registry — matching
17
- # every real projection target (Rust/UL/OIDC all project one domain at
18
- # a time), and deliberately narrower than `Exporter.call`'s own
19
- # multi-domain shape.
5
+ # Projector.call(:ir, bluebook: chapter)
20
6
  #
21
- # ## Three kinds of "project"
22
- #
23
- # Told apart by what they need as input. Only the first belongs in this
24
- # registry.
25
- #
26
- # a projection takes a chapter's declaration and answers something
27
- # that describes the domain: its IR, its storage shape, an OIDC scope
28
- # manifest, the parser's keyword table, the reference pages. Inert,
29
- # derived, and runnable against any chapter that carries what it
30
- # declares it needs. These are what `register` holds.
31
- #
32
- # an export takes a declaration and its bindings and answers
33
- # something that is the domain, running elsewhere — rust/project.rb's
34
- # generated crate, the WASM artifact, the CloudFormation template
35
- # `lib/hecks/projections/deploy` renders. It needs the
36
- # `.world`/`.hecksagon` a projection never looks at, because a
37
- # running system has to know how it is wired. A target that needs
38
- # this declares `needs_world: true` (`Target#projects_as`) and reads
39
- # `options.fetch(:world)`; `Projector.call`'s own `world:` keyword is
40
- # what carries it, merged into `options` before the target ever runs.
41
- #
42
- # a state projection takes records — a domain after dispatch — and is
43
- # a read-model question wearing the same word.
44
- # `bin/expression_projection` is the one of these: its operators are
45
- # not declared anywhere, they are what exists after
46
- # `Grammar.expression` replays expression_operators.json's ledger of
47
- # dispatches. Converting it into this registry would be a category
48
- # error, however much its name suggests otherwise.
49
- #
50
- # ## One word, three other meanings
51
- #
52
- # Worth naming too, because grepping "projection" turns all of these up
53
- # and none is the above:
54
- #
55
- # Ports::Projection read-model catch-up, events folded into state
56
- # bin/project forces that catch-up by hand
57
- # RustProjection rust/project.rb's own separate toolchain
7
+ # A projection is inert and derived from a chapter's declaration. An export
8
+ # (rust crate, WASM, CloudFormation) also needs `.world` bindings and declares
9
+ # `needs_world: true`. State projections (`hecks project_expression_tables`) and
10
+ # `Ports::Projection` read-model catch-up are different things and not registered.
58
11
  module Projector
59
12
  class UnknownProjector < StandardError; end
60
13
  # A chapter-scoped projector was handed something that is not a chapter.
@@ -62,14 +15,8 @@ module Hecks
62
15
 
63
16
  module_function
64
17
 
65
- # `projector` needs only to answer `call(bluebook:, options:)` — a
66
- # module, a class with a class method, or any object responding to
67
- # `call` all work. Re-registering a name replaces it outright,
68
- # deliberately unguarded: a spec re-registering a stub under the same
69
- # name between examples is the ordinary case, not a footgun to fence
70
- # against.
71
18
  # Adds `projector` to the registry under `name`, replacing anything
72
- # already registered there.
19
+ # already registered there (deliberately unguarded, so specs can stub).
73
20
  #
74
21
  # @param name [String, Symbol] the key `projector` is looked up by (converted to a symbol)
75
22
  # @param projector [Module, Class, #call] anything answering `call(bluebook:, options:)`
@@ -81,24 +28,14 @@ module Hecks
81
28
  # Runs the projector registered under `name` against `bluebook`,
82
29
  # after refusing a construct it does not admit.
83
30
  #
84
- # `bluebook:` is kept as the keyword because it is the shipped
85
- # spelling and every existing caller uses it — but what it accepts is
86
- # any construct that emits IR, and `admits!` is what decides whether
87
- # this target can actually take the one handed over.
88
- #
89
31
  # @param name [String, Symbol] the registered projector's key
90
- # @param bluebook [Bluebook::Behaviour::Chapter, Hecks::IR] the chapter or
91
- # IR-emitting construct to project
32
+ # @param bluebook [Bluebook::Behaviour::Chapter, Hecks::IR] the construct to project
92
33
  # @param options [Hash] projector-specific options, passed through unchanged
93
- # @param world [Bluebook::World, nil] the domain's `.world`/`.hecksagon` bindings,
94
- # required by an export (`needs_world: true`); nil for an ordinary projection.
95
- # Merged into `options[:world]` before the target runs — the target never
96
- # receives it as a separate argument.
97
- # @return [Object] whatever the projector's own `call` returns: typically a
98
- # `Hash`/`String` artifact, or a `Hash{String => String}` file tree
34
+ # @param world [Bluebook::World, nil] bindings an export needs (`needs_world: true`);
35
+ # merged into `options[:world]`
36
+ # @return [Object] whatever the projector's own `call` returns
99
37
  # @raise [UnknownProjector] if no projector is registered under `name`
100
- # @raise [WrongConstruct] if `bluebook` lacks a capability or aggregate the
101
- # projector requires, or if the projector needs `world:` and none is given
38
+ # @raise [WrongConstruct] if `bluebook` lacks what the projector requires
102
39
  def call(name, bluebook:, options: {}, world: nil)
103
40
  projector = registry.fetch(name.to_sym) do
104
41
  raise UnknownProjector, "no projector registered for #{name.inspect} — registered: #{registered.sort.inspect}"
@@ -107,31 +44,17 @@ module Hecks
107
44
  projector.call(bluebook: bluebook, options: world ? options.merge(world: world) : options)
108
45
  end
109
46
 
110
- # Refuses `construct` if it lacks a capability or declared aggregate
111
- # `projector` requires. A projection names the capabilities it needs;
112
- # this is what enforces that, before the projector runs.
113
- #
114
- # One check covers both shapes. An ordinary construct includes its
115
- # capabilities and a class-shaped one — Command, Entity, ValueObject
116
- # — extends them, and `is_a?` consults the singleton chain, so it
117
- # answers for an extended module as readily as an included one. This
118
- # started as two checks on the assumption it would not; a spec
119
- # asserting the assumption failed, which is the only reason the
120
- # redundant half was noticed.
47
+ # Refuses `construct` if it lacks a capability or declared aggregate `projector` requires.
48
+ # One `is_a?` check covers included and extended capabilities alike.
121
49
  #
122
50
  # @param name [String, Symbol] the projector's registered key, used in the message
123
- # when refusing
124
- # @param projector [Module, Class, #call] the target being checked; consulted for
125
- # `projection_requires`, `projection_declares`, and `projection_needs_world?` when
126
- # it answers them
127
- # @param construct [Bluebook::Behaviour::Chapter, Hecks::IR] the chapter or
128
- # IR-emitting construct offered to the projector
129
- # @param world [Bluebook::World, nil] the `world:` given to `Projector.call`, checked
130
- # against the target's own `needs_world:` declaration
51
+ # @param projector [Module, Class, #call] the target; consulted for `projection_requires`,
52
+ # `projection_declares` and `projection_needs_world?` when it answers them
53
+ # @param construct [Bluebook::Behaviour::Chapter, Hecks::IR] the construct offered
54
+ # @param world [Bluebook::World, nil] the `world:` given to `Projector.call`
131
55
  # @return [void]
132
- # @raise [WrongConstruct] if `construct` lacks a required capability, the chapter it
133
- # is declares no aggregate the projector needs, or the projector needs `world:`
134
- # and `world` is nil
56
+ # @raise [WrongConstruct] if a required capability or aggregate is missing, or the
57
+ # projector needs `world:` and `world` is nil
135
58
  def admits!(name, projector, construct, world = nil)
136
59
  needed = projector.respond_to?(:projection_requires) ? projector.projection_requires : []
137
60
  missing = needed.reject { |capability| capable?(construct, capability) }
@@ -190,11 +113,8 @@ module Hecks
190
113
  @registry ||= {}
191
114
  end
192
115
 
193
- # A target may be addressed by the constant that implements it
194
- # (`Projections::OIDC`) or by the bare key it registered under
195
- # (`:oidc`). Both resolve here, so the constant form is added
196
- # surface rather than a replacement — every `Projector.call(:ir, ...)`
197
- # written before this existed keeps working untouched.
116
+ # Resolves a target given as a constant (`Projections::OIDC`) or a bare
117
+ # key (`:oidc`) to the key it is registered under.
198
118
  #
199
119
  # @param target [String, Symbol, #projection_key] a registered key, or a target
200
120
  # that declared its own key with `Target#projects_as`
@@ -205,15 +125,10 @@ module Hecks
205
125
  target
206
126
  end
207
127
 
208
- # Writing is the caller's choice, not the projector's. A projector
209
- # returns an artifact and never touches disk, which is what lets
210
- # spec/projector_spec.rb compare `:ir`'s output against a golden
211
- # fixture without a tmpdir. `out:` is the only thing that writes.
128
+ # Writes `artifact` to `out`; a projector itself never touches disk.
212
129
  #
213
- # `as:` comes from the projection's own `emits:` declaration rather
214
- # than from inspecting the artifact. A Hash of path => contents and a
215
- # Hash that simply happens to hold strings are the same object to
216
- # Ruby; only the projection knows which it meant.
130
+ # `as:` comes from the projection's `emits:` declaration, since a file tree
131
+ # and a Hash of strings are the same object to Ruby.
217
132
  #
218
133
  # @param artifact [Hash, String] the projector's output; a file tree when `as: :files`
219
134
  # @param out [String] the path to write to; a directory when `as: :files`
@@ -226,8 +141,7 @@ module Hecks
226
141
  out
227
142
  end
228
143
 
229
- # Answers the paths written, in the order given — so a caller can
230
- # report what happened without re-deriving it from the tree.
144
+ # Writes each `files` entry under `directory`, answering the paths written.
231
145
  #
232
146
  # @param files [Hash{String => String}] relative path => contents
233
147
  # @param directory [String] the directory to write the tree under
@@ -249,8 +163,7 @@ require "json"
249
163
  require_relative "projector/exporter"
250
164
  require_relative "projector/ir_projector"
251
165
  require_relative "projector/target"
252
- # Neither of these requires this file back — they need `Naming` and nothing
253
- # else — so unlike a target they are safe to pull in from here.
166
+ # These need only `Naming`, not this file, so they are safe to load from here.
254
167
  require_relative "projector/docs_projector"
255
168
  require_relative "projector/narrate_projector"
256
169
  require_relative "projector/cli_projector"
@@ -260,9 +173,5 @@ Hecks::Projector.register(:docs, Hecks::Projector::DocsProjector)
260
173
  Hecks::Projector.register(:narrate, Hecks::Projector::NarrateProjector)
261
174
  Hecks::Projector.register(:cli, Hecks::Projector::CliProjector)
262
175
 
263
- # The targets are required from lib/hecks.rb, immediately after this
264
- # file — deliberately not from here. A target requires this file (it
265
- # needs `Target` and the registry), so requiring them back from here
266
- # would close a genuine `circular require considered harmful` loop. Ruby
267
- # tolerates it; the warning is still right, and load order is the kind of
268
- # thing that only breaks once someone requires a target on its own.
176
+ # Targets are required from lib/hecks.rb, not here: each requires this file, so
177
+ # requiring them back would close a circular require.
@@ -0,0 +1,7 @@
1
+ # Binds the `Agent` port to `Agent`; `hecks quality_control mine_combinations` asks it to write candidate domains.
2
+ # Required by name, not relative, so a copy of this directory shares the one implementation loaded.
3
+ require "hecks/quality_control/adapters/agent"
4
+
5
+ Hecks.adapter "Agent" do
6
+ port "Agent"
7
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+ require "shellwords"
5
+
6
+ module Hecks
7
+ module Adapters
8
+ # The `Agent` port's adapter: hands a prompt to an agent on the command line and lets it work
9
+ # in the checkout, the way `hecks quality_control mine_combinations` asks one for candidate
10
+ # domains.
11
+ #
12
+ # Not the interviewer behind the framework's `agent` port (`ClaudeCode`), which reads one
13
+ # JSON answer back: this agent edits files, so the only answer is whether it finished.
14
+ class Agent
15
+ # An agent that could not start, or ended with a failure.
16
+ class Failed < StandardError; end
17
+
18
+ # The command run when neither the caller nor `QA_MINER_AGENT` names one.
19
+ DEFAULT_COMMAND = ["claude", "-p", "--permission-mode", "acceptEdits",
20
+ "--allowedTools", "Read,Glob,Grep,Write,Edit"].freeze
21
+
22
+ # @param aggregate [Object, nil] unused
23
+ # @param settings [Hash] unused
24
+ # @param root [String, nil] unused
25
+ def initialize(aggregate: nil, settings: {}, root: nil); end
26
+
27
+ # The command an ask runs.
28
+ #
29
+ # @param command [String, Array<String>, nil] a command line, or its words
30
+ # @return [Array<String>] `command` as words; `QA_MINER_AGENT` else `DEFAULT_COMMAND` when nil
31
+ def command_for(command = nil)
32
+ command ||= ENV.fetch("QA_MINER_AGENT", nil)
33
+ return DEFAULT_COMMAND unless command
34
+
35
+ command.is_a?(String) ? Shellwords.split(command) : command
36
+ end
37
+
38
+ # Runs the agent with `prompt` on its standard input.
39
+ #
40
+ # @param prompt [String] what the agent is asked to do
41
+ # @param command [String, Array<String>, nil] the agent's command; see `command_for`
42
+ # @param chdir [String] the directory the agent works in
43
+ # @param log [String, nil] a file the agent's output is appended to
44
+ # @return [String] the agent's output
45
+ # @raise [Failed] when the agent cannot start or exits non-zero
46
+ def ask(prompt:, chdir:, command: nil, log: nil)
47
+ words = command_for(command)
48
+ output, status = Open3.capture2e(*words, stdin_data: prompt, chdir: chdir)
49
+ File.open(log, "a") { |file| file.puts(output) } if log
50
+ return output if status.success?
51
+
52
+ raise Failed, "agent exited #{status.exitstatus}: #{output.lines.last(5).join.strip}"
53
+ rescue SystemCallError => e
54
+ raise Failed, "agent could not start (#{words.first}): #{e.message}"
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,7 @@
1
+ # Binds the `AngleTools` port to `AngleTools`, which answers `Angle`'s query: the seed of the backlog.
2
+ # Required by name, not relative, so a copy of this directory shares the one implementation loaded.
3
+ require "hecks/quality_control/adapters/angle_tools"
4
+
5
+ Hecks.adapter "AngleTools" do
6
+ port "AngleTools"
7
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "qa_tool"
4
+
5
+ module Hecks
6
+ module Adapters
7
+ # The `AngleTools` port's adapter: answers `Angle`'s query by running the seed of the backlog.
8
+ class AngleTools < QaTool
9
+ # @return [Hash] `text:` each starting lead's outcome: proposed, or already on file
10
+ def seed
11
+ run_command("qa_seed_angles")
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hecks
4
+ module QA
5
+ # Records what CI said about one commit as a `QualityControl::Clearance`.
6
+ module ClearanceRecorder
7
+ module_function
8
+
9
+ # Conclusions that count as green; same vocabulary as `GithubChecks::PASSING`.
10
+ # A `check_suite` conclusion aggregates one GitHub App's runs only, so callers decide
11
+ # which suites may pass a commit.
12
+ PASSING = %w[success neutral skipped].freeze
13
+
14
+ # Returns the Clearance for `commit`, starting one if none exists.
15
+ # `AlreadyExists` from a redelivered webhook racing another start is swallowed.
16
+ def ensure_started(commit)
17
+ QualityControl::Clearance.find(commit) ||
18
+ QualityControl::Clearance.start!(commit: { value: commit })
19
+ rescue Hecks::Runtime::AlreadyExists
20
+ QualityControl::Clearance.find(commit)
21
+ end
22
+
23
+ # Starts and settles the Clearance for `commit`; the first verdict recorded stands.
24
+ # An already-settled record is returned unchanged, so redelivery cannot raise
25
+ # `LifecycleRefused`.
26
+ #
27
+ # @return the settled Clearance
28
+ def record(commit:, passed:, summary:)
29
+ cleared = ensure_started(commit)
30
+ return cleared if cleared.status != "running"
31
+
32
+ passed ? cleared.passed!(summary: { value: summary }) : cleared.failed!(refusal: { value: summary })
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,7 @@
1
+ # Binds the `ClearanceTools` port to `ClearanceTools`, which answers `Clearance`'s query: the PR check.
2
+ # Required by name, not relative, so a copy of this directory shares the one implementation loaded.
3
+ require "hecks/quality_control/adapters/clearance_tools"
4
+
5
+ Hecks.adapter "ClearanceTools" do
6
+ port "ClearanceTools"
7
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "qa_tool"
4
+
5
+ module Hecks
6
+ module Adapters
7
+ # The `ClearanceTools` port's adapter: answers `Clearance`'s query by running the PR check. A
8
+ # newly red PR ends the check with status 2, which is an answer; anything else it calls an
9
+ # error is refused with its report.
10
+ class ClearanceTools < QaTool
11
+ # @return [Hash] `text:` what the check found for each open PR the ledger tracks
12
+ def check_pull_requests
13
+ run_command("qa_pr_check", answers: [0, 2])
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ # Binds the `GitPr` port to `GitPr`; the ledger's scripts ask it for every `git` and `gh` call.
2
+ # Required by name, not relative, so a copy of this directory shares the one implementation loaded.
3
+ require "hecks/quality_control/adapters/git_pr"
4
+
5
+ Hecks.adapter "GitPr" do
6
+ port "GitPr"
7
+ end
@@ -0,0 +1,226 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "open3"
4
+ require "json"
5
+
6
+ module Hecks
7
+ module Adapters
8
+ # The `GitPr` port's adapter: the `git` and `gh` calls behind a pull request the QA practice
9
+ # opens or checks, and the two rules that need the outside world to answer.
10
+ #
11
+ # The rules a ledger record can answer (the branch prefix, the bug being fixed, the angle
12
+ # being under investigation) are `given`s on `Patch.Open` and `Improvement.Open`. The two
13
+ # here need the repository or a count of today's pull requests: the per-day cap and the fix
14
+ # commit being an ancestor of `HEAD`.
15
+ class GitPr
16
+ # A rule the adapter enforces refused the request; nothing was opened.
17
+ class Refusal < StandardError; end
18
+
19
+ # `git` or `gh` could not do what was asked, whatever the request.
20
+ class CommandFailed < StandardError; end
21
+
22
+ # A commit sha as it may be handed to `git` as a revision.
23
+ SHA_PATTERN = /\A[0-9a-fA-F]{7,40}\z/
24
+
25
+ # The remote a branch is pushed to and `gh pr create --head` reads it from.
26
+ REMOTE = "origin"
27
+
28
+ # What `gh pr view` says when the branch simply has no pull request.
29
+ NO_PR = /no pull requests? found/i
30
+
31
+ # The fields `gh pr view` is asked for when a PR is opened or looked up by branch.
32
+ VIEW_FIELDS = "number,url,headRefName,headRefOid,title,state"
33
+
34
+ # @param aggregate [Object, nil] unused
35
+ # @param settings [Hash] unused
36
+ # @param root [String, nil] unused
37
+ # @param repo_dir [String] the checkout `git` and `gh` run in; `QA_REPO_DIR` picks one so a
38
+ # spec can use a throwaway repository and a fake `gh`
39
+ def initialize(aggregate: nil, settings: {}, root: nil, repo_dir: ENV.fetch("QA_REPO_DIR", Dir.pwd))
40
+ @repo_dir = repo_dir
41
+ end
42
+
43
+ # @return [String] the checkout's current branch
44
+ # @raise [Refusal] when the directory is not a git checkout
45
+ def branch
46
+ out, _err, status = git("rev-parse", "--abbrev-ref", "HEAD")
47
+ raise Refusal, "not a git checkout at #{@repo_dir}" unless status.success?
48
+
49
+ out
50
+ end
51
+
52
+ # @return [String] the commit `HEAD` names
53
+ def head = git("rev-parse", "HEAD").first
54
+
55
+ # Refuses a checkout with uncommitted work, since a PR opened from it would not carry it.
56
+ #
57
+ # @return [void]
58
+ # @raise [Refusal] when `git status` cannot be read or reports changes
59
+ def assert_clean_tree!
60
+ dirty, _err, status = git("status", "--porcelain")
61
+ raise Refusal, "could not read git status at #{@repo_dir}" unless status.success?
62
+ return if dirty.empty?
63
+
64
+ raise Refusal, "the working tree at #{@repo_dir} is dirty — commit or discard first:\n#{dirty}"
65
+ end
66
+
67
+ # Refuses one more pull request than the day's cap allows; a cap of zero is no cap.
68
+ #
69
+ # @param opened_today [Integer] how many PRs the ledger recorded since local midnight
70
+ # @param cap [Integer] `PR_CAP_PER_DAY`
71
+ # @return [void]
72
+ # @raise [Refusal] when `opened_today` has reached a positive `cap`
73
+ def assert_under_daily_cap!(opened_today:, cap:)
74
+ return unless cap.positive? && opened_today >= cap
75
+
76
+ raise Refusal, "#{opened_today} PR(s) already opened since local midnight, and " \
77
+ "QualityControlDials::PR_CAP_PER_DAY is #{cap} — leave this as an open Bug/Angle " \
78
+ "and open it tomorrow, or raise the dial in qa/settings.yml"
79
+ end
80
+
81
+ # Refuses a fix commit that is not part of the branch being opened.
82
+ #
83
+ # @param commit [String] the commit the ledger says fixes the bug
84
+ # @param owner [String] what the commit belongs to, worded into the refusal (`"BUG#1"`)
85
+ # @return [void]
86
+ # @raise [Refusal] when `commit` is not a sha or not an ancestor of `HEAD`
87
+ def assert_ancestor!(commit:, owner:)
88
+ assert_sha!(commit, owner)
89
+ _out, _err, status = git("merge-base", "--is-ancestor", "--", commit, "HEAD")
90
+ return if status.success?
91
+
92
+ raise Refusal, "#{owner}'s own fix commit #{commit[0, 7]} is not an ancestor of HEAD " \
93
+ "(#{head[0, 7]}) on #{branch} — the PR must carry the commit the ledger says fixes it"
94
+ end
95
+
96
+ # Refuses a fix commit that the pushed branch does not carry: `gh pr create --head` opens
97
+ # the pull request from the remote branch, not from the local checkout.
98
+ #
99
+ # @param branch [String] the head branch
100
+ # @param commit [String] the commit the ledger says fixes the bug
101
+ # @param owner [String] what the commit belongs to, worded into the refusal
102
+ # @return [void]
103
+ # @raise [Refusal] when the branch is not on the remote, or its tip does not carry `commit`
104
+ def assert_pushed!(branch:, commit:, owner:)
105
+ assert_sha!(commit, owner)
106
+ out, err, status = git("ls-remote", "--heads", REMOTE, "refs/heads/#{branch}")
107
+ raise Refusal, "could not read #{REMOTE} for #{branch}: #{err}" unless status.success?
108
+
109
+ tip = out.split.first.to_s
110
+ raise Refusal, "#{branch} is not pushed to #{REMOTE} — push it before opening the PR" if tip.empty?
111
+
112
+ assert_carries!(tip, commit, owner, "the pushed #{REMOTE}/#{branch}")
113
+ end
114
+
115
+ # Refuses a pull request whose head does not carry the fix commit.
116
+ #
117
+ # @param head [String] the PR's head commit, as `gh` reports it
118
+ # @param commit [String] the commit the ledger says fixes the bug
119
+ # @param owner [String] what the commit belongs to, worded into the refusal
120
+ # @return [void]
121
+ # @raise [Refusal] when `head` is not a sha, or does not carry `commit`
122
+ def assert_pr_head!(head:, commit:, owner:)
123
+ assert_sha!(commit, owner)
124
+ assert_sha!(head, "the PR head")
125
+ assert_carries!(head, commit, owner, "the PR head")
126
+ end
127
+
128
+ # The open PR for a branch.
129
+ #
130
+ # @param branch [String] the head branch
131
+ # @return [Hash{Symbol => Object}, nil] `gh pr view`'s fields, or nil when no PR is open
132
+ # @raise [CommandFailed] when `gh` failed for any reason but the branch having no PR
133
+ def open_pull_request(branch)
134
+ out, err, status = gh("pr", "view", branch, "--json", VIEW_FIELDS)
135
+ unless status.success?
136
+ return nil if err.match?(NO_PR)
137
+
138
+ raise CommandFailed, "gh pr view #{branch} failed — #{err.empty? ? out : err}"
139
+ end
140
+
141
+ view = JSON.parse(out, symbolize_names: true)
142
+ view[:state] == "OPEN" ? view : nil
143
+ end
144
+
145
+ # Opens a PR from `branch`.
146
+ #
147
+ # @param branch [String] the head branch
148
+ # @param title [String] the PR's title
149
+ # @param body [String] the PR's description
150
+ # @param draft [Boolean] open it as a draft
151
+ # @return [String] what `gh pr create` printed, the PR's URL
152
+ # @raise [CommandFailed] when `gh` refuses
153
+ def create_pull_request(branch:, title:, body:, draft: false)
154
+ args = ["pr", "create", "--head", branch, "--title", title, "--body", body]
155
+ args << "--draft" if draft
156
+ out, err, status = gh(*args)
157
+ raise CommandFailed, "gh pr create failed — #{err.empty? ? out : err}" unless status.success?
158
+
159
+ out
160
+ end
161
+
162
+ # Queues a squash merge for when the PR's checks pass.
163
+ #
164
+ # @param number [Integer] the PR's number
165
+ # @return [void]
166
+ # @raise [CommandFailed] when `gh` refuses
167
+ def merge_when_green(number)
168
+ _out, err, status = gh("pr", "merge", number.to_s, "--auto", "--squash")
169
+ raise CommandFailed, "gh pr merge --auto failed — #{err}" unless status.success?
170
+ end
171
+
172
+ # A tracked PR's state and head commit, read live: a push mints a new commit to clear.
173
+ #
174
+ # @param number [Integer] the PR's number
175
+ # @return [Hash{Symbol => Object}] `state`, `headRefOid` and `url`
176
+ # @raise [CommandFailed] when `gh` cannot read it
177
+ def pull_request(number)
178
+ parse(gh("pr", "view", number.to_s, "--json", "state,headRefOid,url"), "gh pr view failed")
179
+ end
180
+
181
+ # A tracked PR's checks, as `gh` reports them.
182
+ #
183
+ # @param number [Integer] the PR's number
184
+ # @return [Array<Hash{Symbol => Object}>] each check's `name`, `state`, `bucket`, `workflow`
185
+ # @raise [CommandFailed] when `gh` cannot read them
186
+ def checks(number)
187
+ parse(gh("pr", "checks", number.to_s, "--json", "name,state,bucket,workflow"), "gh pr checks failed")
188
+ end
189
+
190
+ private
191
+
192
+ def assert_sha!(value, owner)
193
+ return if value.to_s.match?(SHA_PATTERN)
194
+
195
+ raise Refusal, "#{owner}'s commit #{value.to_s.inspect} does not look like a sha"
196
+ end
197
+
198
+ def assert_carries!(tip, commit, owner, label)
199
+ _out, _err, status = git("merge-base", "--is-ancestor", "--", commit, tip)
200
+ return if status.success?
201
+
202
+ raise Refusal, "#{owner}'s own fix commit #{commit[0, 7]} is not an ancestor of #{label} " \
203
+ "(#{tip[0, 7]}) — the PR must carry the commit the ledger says fixes it"
204
+ end
205
+
206
+ def parse(result, failure)
207
+ out, err, status = result
208
+ raise CommandFailed, "#{failure} — #{err.strip.empty? ? out.strip : err.strip}" unless status.success?
209
+
210
+ JSON.parse(out, symbolize_names: true)
211
+ end
212
+
213
+ def git(*) = run_tool("git", *)
214
+
215
+ def gh(*) = run_tool("gh", *)
216
+
217
+ def run_tool(tool, *)
218
+ out, err, status = Open3.capture3(tool, *, chdir: @repo_dir)
219
+ [out.strip, err.strip, status]
220
+ rescue Errno::ENOENT
221
+ raise Refusal, "#{tool} is not installed or not on PATH (or #{@repo_dir} is missing) — " \
222
+ "the practice cannot open or check a pull request without it"
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,9 @@
1
+ # Binds the `CI` port to `GithubChecks` for any boot that loads the QualityControl chapter.
2
+ # The implementation is required by name, not relative to this file, because the `.adapter` glob
3
+ # never loads the sibling `.rb` and a copy of this directory (a fuzz boot) must share the one
4
+ # implementation already loaded.
5
+ require "hecks/quality_control/adapters/github_checks"
6
+
7
+ Hecks.adapter "GithubChecks" do
8
+ port "CI"
9
+ end