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
@@ -6,18 +6,20 @@ require_relative "../naming"
6
6
 
7
7
  module Hecks
8
8
  module Runtime
9
+ # Raised when a registry can't resolve required wiring: an unbound aggregate, an
10
+ # unknown adapter, or a port/adapter mismatch.
9
11
  class WiringError < StandardError; end
10
12
 
11
- # The collections a boot gathers — bluebooks, hexagons, ports, adapters,
12
- # worlds, the logs — and how a repository is resolved from them. The
13
- # wiring gate lives in registry/verification.rb, saga persistence
14
- # resolution in registry/saga_persistence.rb, and a `.world`'s project-wide
15
- # defaults in registry/world_defaults.rb.
13
+ # The collections a boot gathers: bluebooks, hecksagons, ports, adapters, worlds, and logs.
14
+ # Wiring verification, saga persistence, and world defaults live under registry/.
16
15
  class Registry
17
16
  include Verification
18
17
  include SagaPersistence
19
18
  include WorldDefaults
20
19
 
20
+ # The thread-local key under which open reaction collections are kept.
21
+ REACTION_SINKS = :hecks_reaction_sinks
22
+
21
23
  attr_reader :root, :bluebooks, :hecksagons, :ports, :adapters, :worlds, :event_log,
22
24
  :reaction_log, :saga_log, :saga_instances, :translations, :saga_mutex,
23
25
  :saga_dispatch_log, :policy_dispatch_log, :bluebook_sources,
@@ -38,98 +40,50 @@ module Hecks
38
40
  @translations = []
39
41
  @event_log = []
40
42
  @reaction_log = []
43
+ @reaction_events = {}.compare_by_identity
41
44
  @saga_log = []
42
- # A declarative fact, not yet a dispatched one — `AggregateDoor#
43
- # mark_sensitive` (called from a `.hecksagon` file, the same way
44
- # `port`/`persisted_by` already are) appends here at
45
- # hecksagon-build time; `Runtime::Loader.boot`'s own post-dispatcher
46
- # step turns each entry into a real `Privacy::Marking.Mark`,
47
- # idempotently, the same "declared here, taken effect once boot
48
- # actually has a dispatcher" shape `redrive_outbox!` already has.
45
+ # Recorded at hecksagon-build time (AggregateDoor#mark_sensitive); Loader.boot's
46
+ # post-dispatch step turns each entry into a real Privacy::Marking.Mark, idempotently.
49
47
  @pending_privacy_markings = []
50
- # **Additive, Ruby-only** — never merged into saga_log/reaction_log.
51
- # rust/src/kernel/orchestrate.rs ports those two arrays' exact
52
- # shape byte-for-byte (spec/rust_conformance_spec.rb's own
53
- # equality check) — a landmine found by reading that spec before
54
- # touching anything, not by hitting it. These carry the raw
55
- # inputs a dispatch's own argument binding was resolved from
56
- # (SagaInterpreter#deliver_saga_dispatch / PolicyInterpreter#
57
- # trigger_args), for Properties.dispatch_binding_fidelity's own
58
- # independent re-derivation — a fact neither existing log
59
- # records at all, so there is nothing here for Rust to have
60
- # matched or drifted from.
48
+ # Ruby-only; unlike saga_log/reaction_log (ported byte-for-byte to
49
+ # rust/src/kernel/orchestrate.rs, per spec/rust_conformance_spec.rb), these carry
50
+ # the raw dispatch-binding inputs Properties.dispatch_binding_fidelity re-derives.
61
51
  @saga_dispatch_log = []
62
52
  @policy_dispatch_log = []
63
53
  @saga_instances = Hash.new { |h, k| h[k] = {} }
64
- # Guards `saga_instances`' own mutation+checkpoint sequence
65
- # (`SagaInterpreter`'s 4 write points, §7) — the same shape of
66
- # hazard this codebase's own prior audit already flagged for
67
- # `Dispatcher#reenter`'s reaction-depth counter (M20: a
68
- # thread-shared ivar with no lock, since fixed by moving it to
69
- # `Thread.current`, dispatcher.rb), made meaningfully easier to
70
- # hit here once a persistence write sits in the same critical
71
- # section. Held across the in-memory
72
- # mutation and the checkpoint write together, never across a
73
- # saga's own dispatch cascade — see `SagaInterpreter#advance_saga`'s
74
- # own comment for why that distinction matters (non-reentrant
75
- # Mutex, recursive re-entry is real).
54
+ # Guards saga_instances' mutation+checkpoint sequence together, never held across a
55
+ # saga's own dispatch cascade — Mutex is non-reentrant and recursive re-entry is real.
76
56
  @saga_mutex = Mutex.new
77
57
  @repositories = {}
78
58
  @projection_repositories = {}
79
59
  @bluebook_builders = {}
80
- # **Eager, not lazy** — see `#resolved_eras`'s own comment for why. Built
81
- # here rather than `@resolved_eras ||= {}` on first access so there is
82
- # no window, post-boot, where two concurrently dispatching threads
83
- # could race creating this Hash (Hecks/ThreadSharedIvarMutation; the
84
- # same shape of hazard `Dispatcher#reenter`'s `@reaction_depth` was
85
- # fixed for). Every write into it still only ever happens at boot,
86
- # single-threaded (`EraResolver.check!`, a `:pre_verify` boot gate) —
87
- # this only removes the race on standing up the container itself for
88
- # a boot with no era-plugin domain at all, whose first touch would
89
- # otherwise be a live dispatch's own `RepositoryFactory.build` read.
60
+ # Eager, not lazy: avoids a race where two dispatching threads could create this
61
+ # Hash on first access. All writes still happen at boot, single-threaded
62
+ # (EraResolver.check!).
90
63
  @resolved_eras = {}
91
- # The sibling fact `EraResolver.check!` records for an old checkout:
92
- # domain name -> the newest held ordinal that superseded the era this
93
- # boot resolved to; absent for every domain booting the current era.
94
- # `RepositoryFactory.build` hands it to the adapter as
95
- # `superseded_by:`, and `PostgresEra#append` refuses on it before
96
- # ever issuing an INSERT — the in-process half of the era fence, the
97
- # half that holds even for a connection row-level security cannot
98
- # bite (BUG#24). Eager for exactly the reason `@resolved_eras` is.
64
+ # domain name -> the ordinal that superseded this boot's era, for an old checkout only.
65
+ # RepositoryFactory.build passes it to PostgresEra#append, which refuses before the
66
+ # INSERT — the in-process half of the era fence. Eager for the same reason as
67
+ # @resolved_eras.
99
68
  @superseded_eras = {}
100
- # **Eager, not lazy** — see `#capability_graph`'s own comment for why.
101
- # `CapabilityGraph.new` only stores the registry reference; there is
102
- # no reason to defer it, and doing so removes the exact same
103
- # first-access race `#resolved_eras` above does, while preserving the
104
- # "same instance every call" identity `spec/runtime/capability_graph_
105
- # spec.rb` already requires.
69
+ # Eager: CapabilityGraph.new only stores the registry reference, and eager
70
+ # construction avoids the same first-access race as @resolved_eras while
71
+ # keeping one instance per registry.
106
72
  @capability_graph = CapabilityGraph.new(self)
107
- # `@saga_persistence` itself is eager (see `#saga_persistence`'s own
108
- # comment) — only the per-domain resolution inside it is genuinely
109
- # expensive and lazy, guarded by this dedicated mutex. Not the same
110
- # mutex as `@saga_mutex`: `checkpoint` (saga_interpreter.rb) calls
111
- # `saga_persistence(domain)` from inside an `@saga_mutex.synchronize`
112
- # block, so reusing `@saga_mutex` here would deadlock the very first
113
- # time a saga advanced (a `Mutex` is not reentrant — the exact
114
- # warning `@saga_mutex`'s own comment already gives for a different
115
- # reason).
73
+ # Guards only the lazy per-domain resolution inside @saga_persistence. Must not reuse
74
+ # @saga_mutex: checkpoint calls saga_persistence(domain) from inside
75
+ # @saga_mutex.synchronize, and Mutex is not reentrant.
116
76
  @saga_persistence = {}
117
77
  @saga_persistence_mutex = Mutex.new
118
78
  @outbox = Outbox::Relay.new(self)
119
79
  end
120
80
 
121
- # **The outbox relay** — one per registry, for its whole life (built
122
- # here, never swapped, so no thread ever sees a different one).
123
- # It can enqueue from the moment the registry exists; a Dispatcher
124
- # attaches the interpreters that let it deliver. See
125
- # `Runtime::Outbox`.
81
+ # One outbox per registry, built once here and never swapped. Can enqueue immediately;
82
+ # a Dispatcher attaches the interpreters that let it deliver (see Runtime::Outbox).
126
83
  attr_reader :outbox
127
84
 
128
- # The builder stays open for the life of this registry, keyed by chapter
129
- # name — see the comment on `BluebookBuilder.build`. A chapter split across
130
- # several files (`language/bluebook/*.bluebook`, all `Hecks.bluebook "Bluebook"`)
131
- # needs its declarations to accumulate into one builder rather than each
132
- # file minting its own and silently discarding the one before.
85
+ # Stays open for the life of the registry, keyed by chapter name, so a chapter split
86
+ # across several files (language/bluebook/*.bluebook) accumulates into one builder.
133
87
  #
134
88
  # @param name [String, Symbol] the chapter name the builder accumulates
135
89
  # declarations for
@@ -142,19 +96,9 @@ module Hecks
142
96
  @bluebook_builders[name.to_s] ||= yield
143
97
  end
144
98
 
145
- # Boot-time-only, single-threaded — every `add_*` below (through
146
- # `add_translation`) is called exclusively from `Hecks.collect`
147
- # (hecks.rb), which is what `Hecks.bluebook`/`.hecksagon`/`.port`/
148
- # `.adapter`/`.world`/`.translation` run inside while a `.bluebook`/
149
- # `.hecksagon`/`.world` file is being `Kernel.load`ed — i.e. strictly
150
- # during `Loader.boot`/`.boot_files`, before `dispatcher_for` ever
151
- # hands this registry to a live, multi-threaded caller. Nothing
152
- # downstream of boot ever calls these — verified by grepping every
153
- # call site in lib/ and spec/ before writing this — so unlike
154
- # `#resolved_eras`/`#capability_graph`/`#saga_persistence` (each
155
- # reachable from live dispatch, and fixed for real above/in
156
- # registry/saga_persistence.rb) there is no concurrent caller for
157
- # `Hecks/ThreadSharedIvarMutation` to actually be warning about here.
99
+ # Boot-time-only, single-threaded: every add_* below runs from Hecks.collect while a
100
+ # .bluebook/.hecksagon/.world file is being Kernel.loaded, strictly during Loader.boot,
101
+ # before dispatcher_for hands this registry to a live, multi-threaded caller.
158
102
  # rubocop:disable Hecks/ThreadSharedIvarMutation
159
103
  # Registers a loaded chapter, keyed by its own declared name.
160
104
  #
@@ -162,19 +106,20 @@ module Hecks
162
106
  # @return [Bluebook::Chapter] `item`, unchanged
163
107
  def add_bluebook(item) = @bluebooks[item.name] = item
164
108
 
165
- # Provenance, side-channel — which real `.bluebook` file(s)
166
- # contributed to a chapter name, never part of the exported IR (a
167
- # boot-time loading fact, not a domain fact) and never Rust-mirrored
168
- # (the same "additive, Ruby-only" shape `@translations` above already
169
- # is). Legitimate accumulation (several files declaring the same
170
- # chapter name on purpose — `lib/hecks/language/bluebook/*.bluebook`
171
- # all open `Hecks.bluebook "Bluebook"`) pushes more than one path
172
- # here too; that alone is not a problem. What this exists to let
173
- # `refuse_cross_package_bluebook_merge!` (registry/verification.rb)
174
- # catch is two unrelated packages accumulating into the same name by
175
- # coincidence — a stale vendored fork's own copy of a real gem's
176
- # chapter, still reachable on the load path, silently merging its
177
- # aggregates into the real one via this exact accumulation mechanism.
109
+ # Drops a chapter and the open builder and source record that accumulated it, so the
110
+ # chapter can be loaded again from nothing.
111
+ #
112
+ # @param name [String, Symbol] the chapter name to forget
113
+ # @return [void]
114
+ def forget_chapter(name)
115
+ @bluebooks.delete(name.to_s)
116
+ @bluebook_builders.delete(name.to_s)
117
+ @bluebook_sources.delete(name.to_s)
118
+ end
119
+
120
+ # Tracks which .bluebook file(s) contributed to a chapter name (a boot-time loading
121
+ # fact, never Rust-mirrored) so refuse_cross_package_bluebook_merge! can catch two
122
+ # unrelated packages accumulating into the same name by coincidence.
178
123
  #
179
124
  # @param name [String, Symbol] the chapter name the file contributed to
180
125
  # @param path [String] the `.bluebook` file that declared it
@@ -183,12 +128,8 @@ module Hecks
183
128
  (@bluebook_sources[name.to_s] ||= []) << path
184
129
  end
185
130
 
186
- # Merged, not replaced — recovered, not new (see Runtime::Loader
187
- # .boot's own comment for the provenance). A domain's hecksagon can
188
- # now load in more than one block for the same domain (base file
189
- # plus an `environments/<name>.hecksagon` overlay), and the second
190
- # block should add to what the first declared, not silently
191
- # discard it.
131
+ # Merges into any wiring already registered for the domain rather than replacing it,
132
+ # so a base .hecksagon file plus an environments/<name>.hecksagon overlay both take effect.
192
133
  #
193
134
  # @param item [Bluebook::Hecksagon] the declared wiring to register
194
135
  # @return [void]
@@ -230,16 +171,10 @@ module Hecks
230
171
  # @return [Bluebook::Adapter] `item`, unchanged
231
172
  def add_adapter(item) = @adapters[item.name] = item
232
173
 
233
- # Merged, not replaced — the same generalization for `World` that
234
- # `add_hecksagon` above recovers for `Hecksagon`: an
235
- # `environments/<name>.world` overlay (or a host-owned tenancy
236
- # overlay world, same mechanism) can now add or override settings
237
- # for a domain a base `.world` file already declared, without
238
- # restating everything the base file said. Settings merge shallow,
239
- # keyed exactly the way WorldBuilder already stores them (both the
240
- # bare verb key and the `"verb:adapter"` qualified key point at the
241
- # same resolved hash) — an overlay's key wins over the base's same
242
- # key; a key only the base declares survives untouched.
174
+ # Merges into any world already registered for the domain, the same shape as
175
+ # add_hecksagon. Settings merge shallow, keyed by verb (and "verb:adapter"); an
176
+ # overlay key wins over the base's same key, and a key only the base declares
177
+ # survives untouched.
243
178
  #
244
179
  # @param item [Bluebook::World] the declared world settings to register
245
180
  # @return [void]
@@ -255,13 +190,10 @@ module Hecks
255
190
  # `item` last
256
191
  def add_translation(item) = @translations << item
257
192
 
258
- # Declares one attribute of one domain's own aggregate sensitive — called from a
259
- # terminal `has_<category>(readable_by:)` on a `Bluebook::DSL::AttributePath`
260
- # (reached by chaining off a bare `Domain::Aggregate` inside a `.hecksagon` file
261
- # being `Kernel.load`ed, or off an already-installed `AggregateDoor`), same timing
262
- # (and same thread-safety argument, above) as `add_bluebook`/`add_port`. Recorded,
263
- # not dispatched: `Runtime::Loader.boot`'s own `seed_privacy_markings!` turns each
264
- # entry into a real `Privacy::Marking.Mark` once a dispatcher exists.
193
+ # Declares one attribute of a domain's aggregate sensitive, called from a terminal
194
+ # has_<category>(readable_by:). Recorded, not dispatched: Loader.boot's
195
+ # seed_privacy_markings! turns each entry into a real Privacy::Marking.Mark once a
196
+ # dispatcher exists.
265
197
  #
266
198
  # @param domain [String] the marked attribute's own aggregate FQN, e.g.
267
199
  # `"Site::Registration"`
@@ -276,16 +208,11 @@ module Hecks
276
208
  end
277
209
  # rubocop:enable Hecks/ThreadSharedIvarMutation
278
210
 
279
- # {domain name => era ordinal} as resolved by the boot-time era
280
- # gate. A lineage adapter writes into its own era's partition —
281
- # which, for an old checkout booting a held-but-superseded shape,
282
- # is not the newest one. The Hash itself is stood up in `initialize`
283
- # (see that comment) — this is a plain reader, not a memoizer;
284
- # `Hecks/ThreadSharedIvarMutation` is the reason there is no `||=`
285
- # left here to flag.
211
+ # {domain name => era ordinal} resolved by the boot-time era gate. Stood up eagerly
212
+ # in initialize; this is a plain reader, not a memoizer.
286
213
  attr_reader :resolved_eras
287
- # Domain name -> the ordinal that superseded this boot's own era, for
288
- # an old checkout only — see `initialize`'s own comment on it.
214
+ # Domain name -> the ordinal that superseded this boot's own era, for an old
215
+ # checkout only.
289
216
  attr_reader :superseded_eras
290
217
 
291
218
  # Finds a loaded chapter by name.
@@ -314,18 +241,14 @@ module Hecks
314
241
  # @return [Array<String>] every declared verb, across every loaded chapter
315
242
  def verbs = @bluebooks.values.flat_map(&:verbs).sort
316
243
 
317
- # The chapter that answers a role check for `domain` — the domain's
318
- # own chapter, or any framework member its hecksagon attaches, that
319
- # declares `provides "authorization"`. Nil when none does. Replaces
320
- # every check for the literal name "Governance": Governance is
321
- # recognised by what it declares, and a chapter that declares the
322
- # same thing is recognised the same way.
244
+ # The chapter that answers a role check for `domain`: the domain's own chapter, or
245
+ # a framework member its hecksagon attaches, that declares `provides "authorization"`.
323
246
  #
324
247
  # @param domain [String, Symbol] the domain whose role checks are being resolved
325
248
  # @return [Bluebook::Chapter, nil] the chapter that answers `domain`'s role
326
249
  # checks, or nil if none does
327
250
  def authorization_provider_for(domain)
328
- names = [domain.to_s, *Array(hecksagon(domain)&.framework_members)]
251
+ names = [domain.to_s, *Array(hecksagon(domain)&.member_chapters)]
329
252
  names.filter_map { |name| bluebook(name) }
330
253
  .find { |chapter| chapter.provides?(Bluebook::Capabilities::AUTHORIZATION) }
331
254
  end
@@ -338,45 +261,32 @@ module Hecks
338
261
  @bluebooks.values.select { |chapter| chapter.provides?(Bluebook::Capabilities::AUTHORIZATION) }
339
262
  end
340
263
 
341
- # The chapter that answers "who is this authenticated pair" for
342
- # `domain` — the domain's own chapter, or any framework member its
343
- # hecksagon attaches, that declares `provides "identity"`. Nil when
344
- # none does. Replaces every check for the literal name "Identity":
345
- # Identity is recognised by what it declares (Register/Link/ResolvedBy),
346
- # and a chapter that declares the same thing is recognised the same way.
264
+ # The chapter that answers "who is this authenticated pair" for `domain`: the
265
+ # domain's own chapter, or a framework member its hecksagon attaches, that
266
+ # declares `provides "identity"`.
347
267
  #
348
268
  # @param domain [String, Symbol] the domain whose identity chapter is being resolved
349
269
  # @return [Bluebook::Chapter, nil] the chapter that answers `domain`'s identity
350
270
  # questions, or nil if none does
351
271
  def identity_provider_for(domain)
352
- names = [domain.to_s, *Array(hecksagon(domain)&.framework_members)]
272
+ names = [domain.to_s, *Array(hecksagon(domain)&.member_chapters)]
353
273
  attached = names.filter_map { |name| bluebook(name) }
354
274
  .find { |chapter| chapter.provides?(Bluebook::Capabilities::IDENTITY) }
355
275
  return attached if attached
356
276
 
357
- # Sibling hecksagons — a consuming domain often wires Identity as
358
- # `Hecks.hecksagon "Identity"` (so Register can attach Governance
359
- # on that named hexagon), not only via uses_framework on the
360
- # consuming domain. The chapter is loaded; it just isn't listed
361
- # on the consumer's own hexagon.
277
+ # Falls back to any loaded chapter: a consuming domain often wires Identity as
278
+ # Hecks.hecksagon "Identity" rather than via uses_framework, so it's loaded but
279
+ # not listed on the consumer's own hexagon.
362
280
  @bluebooks.values.find { |chapter| chapter.provides?(Bluebook::Capabilities::IDENTITY) }
363
281
  end
364
282
 
365
- # The chapter that answers "who may sign in" for `domain` — the
366
- # domain's own chapter, any framework member its hecksagon attaches,
367
- # or any vendored embryonaut bluebook it attaches, that declares
368
- # `provides "membership"`. Nil when none does. Replaces rust/host's
369
- # own HECKS_MEMBERSHIP_AGGREGATE env var: Membership is recognised
370
- # by what it declares (Person.Admit/GrantAccess/All), and a chapter
371
- # that declares the same thing (Embryonaut::Member, say) is
372
- # recognised the same way.
373
- #
374
- # Vendored packages are included here and not in
375
- # `authorization_provider_for` because membership is a vendored
376
- # embryonaut_bluebooks chapter (`uses_embryonaut_bluebook
377
- # "membership"`), not a framework member shipped inside hecks.
378
- # `Naming.pascal` is the same directory-to-chapter convention
379
- # `EmbryonautBluebook.load!` already uses.
283
+ # The chapter that answers "who may sign in" for `domain`: the domain's own
284
+ # chapter, a framework member, or a vendored embryonaut bluebook it attaches,
285
+ # that declares `provides "membership"`.
286
+ #
287
+ # Vendored packages are included here (unlike `authorization_provider_for`)
288
+ # because membership ships as a vendored embryonaut_bluebooks chapter, not a
289
+ # framework member.
380
290
  #
381
291
  # @param domain [String, Symbol] the domain whose sign-in aggregate is being resolved
382
292
  # @return [Bluebook::Chapter, nil] the chapter that answers `domain`'s membership
@@ -385,12 +295,9 @@ module Hecks
385
295
  vendored_provider_for(domain, Bluebook::Capabilities::MEMBERSHIP)
386
296
  end
387
297
 
388
- # The chapter that answers the guest newsletter signup for `domain` —
389
- # the domain's own chapter, a framework member, or a vendored
390
- # embryonaut bluebook it attaches, that declares `provides
391
- # "newsletter"`. Nil when none does. Newsletter is recognised by
392
- # what it declares (Subscribe/AddName/Confirm/Unsubscribe), so a
393
- # chapter that declares the same thing is recognised the same way.
298
+ # The chapter that answers the guest newsletter signup for `domain`: the domain's
299
+ # own chapter, a framework member, or a vendored embryonaut bluebook it attaches,
300
+ # that declares `provides "newsletter"`.
394
301
  #
395
302
  # @param domain [String, Symbol] the domain whose newsletter chapter is being resolved
396
303
  # @return [Bluebook::Chapter, nil] the chapter that answers `domain`'s newsletter
@@ -410,9 +317,8 @@ module Hecks
410
317
  vendored_provider_for(domain, Bluebook::Capabilities::NEWSLETTER_ISSUES)
411
318
  end
412
319
 
413
- # The chapter that answers scheduling sessions and taking registrations
414
- # for `domain` — resolved the same way as `payments_provider_for`, by what
415
- # it declares (`provides "registrations"`). Nil when none does.
320
+ # The chapter that answers scheduling sessions and registrations for `domain`,
321
+ # resolved the same way as `payments_provider_for`, by declaring `provides "registrations"`.
416
322
  #
417
323
  # @param domain [String, Symbol] the domain whose registrations chapter is being resolved
418
324
  # @return [Bluebook::Chapter, nil] the chapter that answers `domain`'s registrations,
@@ -425,19 +331,17 @@ module Hecks
425
331
  # `domain` — resolved by what it declares (`provides "payment_connection"`).
426
332
  # Nil when none does.
427
333
  #
428
- # @param domain [String, Symbol] the domain whose payment-connection chapter is being resolved
334
+ # @param domain [String, Symbol] the domain whose payment-connection chapter is
335
+ # being resolved
429
336
  # @return [Bluebook::Chapter, nil] the chapter that owns `domain`'s payment connection,
430
337
  # or nil if none does
431
338
  def payment_connection_provider_for(domain)
432
339
  vendored_provider_for(domain, Bluebook::Capabilities::PAYMENT_CONNECTION)
433
340
  end
434
341
 
435
- # The chapter that takes payments for `domain` — the domain's own
436
- # chapter, a framework member, or a vendored embryonaut bluebook it
437
- # attaches, that declares `provides "payments"`. Nil when none does.
438
- # Payments is recognised by what it declares (Initiate and the
439
- # processor's two verdicts), so a chapter that declares the same
440
- # thing is recognised the same way.
342
+ # The chapter that takes payments for `domain`: the domain's own chapter, a
343
+ # framework member, or a vendored embryonaut bluebook it attaches, that
344
+ # declares `provides "payments"`.
441
345
  #
442
346
  # @param domain [String, Symbol] the domain whose payments chapter is being resolved
443
347
  # @return [Bluebook::Chapter, nil] the chapter that takes `domain`'s payments, or nil
@@ -446,14 +350,13 @@ module Hecks
446
350
  vendored_provider_for(domain, Bluebook::Capabilities::PAYMENTS)
447
351
  end
448
352
 
449
- # The chapter that provides `capability` for `domain`: the domain's
450
- # own chapter, any framework member its hecksagon attaches, or any
451
- # vendored embryonaut bluebook it attaches, that declares it. Falls
452
- # back to any loaded chapter that does, because a consuming domain
453
- # often wires a vendored chapter as its own `Hecks.hecksagon "Name"`
454
- # (so that chapter can attach Governance on that named hexagon)
455
- # rather than via `uses_embryonaut_bluebook` on itself — the chapter
456
- # is loaded, it just isn't listed on the consumer's own hexagon.
353
+ # The chapter that provides `capability` for `domain`: the domain's own chapter,
354
+ # a framework member its hecksagon attaches, or a vendored embryonaut bluebook
355
+ # it attaches, that declares it.
356
+ #
357
+ # Falls back to any loaded chapter, since a consuming domain often wires a
358
+ # vendored chapter as its own `Hecks.hecksagon "Name"` rather than via
359
+ # `uses_embryonaut_bluebook`, so it's loaded but not listed on the consumer's hexagon.
457
360
  #
458
361
  # @param domain [String, Symbol] the domain the provider is resolved for
459
362
  # @param capability [String] the capability's name, such as
@@ -462,7 +365,7 @@ module Hecks
462
365
  def vendored_provider_for(domain, capability)
463
366
  hexagon = hecksagon(domain)
464
367
  vendored = Array(hexagon&.vendored_bluebooks).map { |name| Naming.pascal(name) }
465
- names = [domain.to_s, *Array(hexagon&.framework_members), *vendored]
368
+ names = [domain.to_s, *Array(hexagon&.member_chapters), *vendored]
466
369
  attached = names.filter_map { |name| bluebook(name) }
467
370
  .find { |chapter| chapter.provides?(capability) }
468
371
  return attached if attached
@@ -485,38 +388,57 @@ module Hecks
485
388
  @repositories[[domain.to_s, aggregate.hecks_name]] ||= Ports::Persistence.repository(self, domain, aggregate)
486
389
  end
487
390
 
488
- # Everything a dispatch wrote, cleared; nothing a boot declared,
489
- # touched. Bluebooks, hecksagons, ports, adapters, worlds and the
490
- # resolved eras are what loading the files produced and stay as
491
- # they are; the logs, the saga instances and the repositories are
492
- # what running commands against them produced, and go back to
493
- # exactly what a fresh boot of the same files hands out. Dropping
494
- # the repositories (rather than emptying each) is deliberate: a
495
- # fresh boot's own repositories are new adapter instances too, so
496
- # a Memory adapter starts empty and a durable one sees whatever
497
- # it persisted — the same reading either way. Sagas rehydrate off
498
- # that store again, the way `Loader.boot_files` does after
499
- # `verify!`.
500
- #
501
- # What this is for: a test runner that would otherwise boot a runtime
502
- # per test to get isolation (`Behaviors::Expectations.run_one`) — ~2s a
503
- # boot, 76 chess behaviours = two and a half minutes of booting the
504
- # same two files — can now boot once and reset between tests.
505
- #
506
- # Single-threaded caller, the same reason the `add_*` cluster above
507
- # is exempt — `Behaviors::Expectations.run_one` is this method's only
508
- # caller (verified by grep before writing this), and it runs one
509
- # test at a time: `Runner#run` maps over tests sequentially, and
510
- # `Behaviors.rspec`'s generated examples run under RSpec's own
511
- # single-threaded example loop. No production dispatch path calls
512
- # this at all — a live Puma worker pool never resets a registry out
513
- # from under itself mid-flight.
391
+ # Records one policy reaction on the shared log, and on every collection open on this
392
+ # thread (see `collecting_reactions`).
393
+ #
394
+ # The event that triggered a reaction is kept beside the log, not in the record: the record
395
+ # is the byte-for-byte shape the Rust kernel also writes.
396
+ #
397
+ # @param record [Hash{Symbol => Object}] the reaction's outcome
398
+ # @param event [String, Integer, nil] identity of the event instance the reaction answered
399
+ # @return [void]
400
+ # rubocop:disable-next Hecks/ThreadSharedIvarMutation
401
+ def log_reaction(record, event: nil)
402
+ @reaction_log << record
403
+ @reaction_events[record] = event if event
404
+ Array(Thread.current[REACTION_SINKS]).each { |sink| sink << record }
405
+ end
406
+
407
+ # The identity of the event instance a logged reaction answered.
408
+ #
409
+ # @param record [Hash{Symbol => Object}] a record `log_reaction` was given
410
+ # @return [String, Integer, nil] nil for a record logged without its event
411
+ def reaction_event(record) = @reaction_events[record]
412
+
413
+ # Collects the reactions logged on this thread while the block runs, so one dispatch
414
+ # reads exactly its own even when other threads dispatch on the same registry. Nested
415
+ # dispatches (a reaction that dispatches) each collect, and the outer one sees theirs too.
416
+ #
417
+ # @yield [Array<Hash>] the collection, filled as reactions are logged
418
+ # @return [Object] what the block returns
419
+ def collecting_reactions
420
+ sinks = (Thread.current[REACTION_SINKS] ||= [])
421
+ sink = []
422
+ sinks << sink
423
+ yield sink
424
+ ensure
425
+ sinks&.delete_if { |candidate| candidate.equal?(sink) }
426
+ end
427
+
428
+ # Clears everything a dispatch produced (logs, saga instances, repositories); leaves
429
+ # what booting the files produced (bluebooks, hecksagons, ports, adapters, worlds,
430
+ # resolved eras) untouched.
431
+ #
432
+ # Repositories are dropped, not emptied, so a fresh Memory adapter starts empty while
433
+ # a durable one still sees what it persisted. Single-threaded caller only
434
+ # (Behaviors::Expectations.run_one runs one test at a time).
514
435
  #
515
436
  # @return [Runtime::Registry] self
516
437
  # rubocop:disable-next Hecks/ThreadSharedIvarMutation
517
438
  def reset_runtime_state!
518
439
  @event_log.clear
519
440
  @reaction_log.clear
441
+ @reaction_events.clear
520
442
  @saga_log.clear
521
443
  @saga_dispatch_log.clear
522
444
  @policy_dispatch_log.clear
@@ -528,10 +450,8 @@ module Hecks
528
450
  self
529
451
  end
530
452
 
531
- # Built eagerly in `initialize` (see that comment) — this is a plain
532
- # reader, not a memoizer; `spec/runtime/capability_graph_spec.rb`
533
- # asserts the same instance comes back every call, which this still
534
- # gives, just without a lazy `||=` race on standing it up.
453
+ # Built eagerly in `initialize`; this is a plain reader, not a memoizer.
454
+ # `spec/runtime/capability_graph_spec.rb` asserts the same instance comes back every call.
535
455
  attr_reader :capability_graph
536
456
 
537
457
  # Resolves and memoizes the repository to read `aggregate` from — a caught-up
@@ -583,15 +503,10 @@ module Hecks
583
503
  false
584
504
  end
585
505
 
586
- # Recovered — see `add_hecksagon`'s own comment for provenance.
587
- # Concatenates every list-shaped fact; `binds` in particular is
588
- # additive because an overlay rebinding an aggregate (a new
589
- # `persisted_by` for the same aggregate/verb) is meant to shadow
590
- # the base's own bind at resolution time, not erase it outright —
591
- # `Ports::Persistence::BindingPolicy.resolve`'s own "exactly one
592
- # authoritative bind" check is what actually catches a genuine
593
- # double-bind; this merge only concatenates, it does not itself
594
- # decide which of two binds for the same aggregate wins.
506
+ # Concatenates every list-shaped fact from base and overlay. `binds` is additive too:
507
+ # an overlay rebinding an aggregate is meant to shadow the base's bind at resolution
508
+ # time, not erase it — `Ports::Persistence::BindingPolicy.resolve`'s "exactly one
509
+ # authoritative bind" check is what actually catches a genuine double-bind.
595
510
  #
596
511
  # @param base [Bluebook::Hecksagon] the domain's already-registered wiring
597
512
  # @param overlay [Bluebook::Hecksagon] the newly loaded block's own wiring to
@@ -599,30 +514,24 @@ module Hecks
599
514
  # @return [Bluebook::Hecksagon] a new wiring with every list-shaped fact
600
515
  # concatenated, `base` then `overlay`
601
516
  def merge_hecksagons(base, overlay)
602
- # Same-name blocks concatenate regardless of which file they came
603
- # from (`site.hecksagon`, `context_map.hecksagon`, an
604
- # environment overlay). Order-independent: list facts uniq, so
605
- # loading context_map before or after the domain file is the same
606
- # merged hecksagon. Binds stay concatenated (BindingPolicy still
607
- # refuses a genuine double-bind).
517
+ # Order-independent: list facts uniq, so loading context_map before or after the
518
+ # domain file yields the same merged hecksagon.
608
519
  Bluebook::Hecksagon.new(
609
520
  domain: base.domain,
610
521
  binds: base.binds + overlay.binds,
611
522
  subscriptions: (base.subscriptions + overlay.subscriptions).uniq,
612
523
  framework_members: (base.framework_members + overlay.framework_members).uniq,
613
524
  vendored_bluebooks: (base.vendored_bluebooks + overlay.vendored_bluebooks).uniq,
525
+ attached_chapters: (base.attached_chapters + overlay.attached_chapters).uniq,
614
526
  bounded: base.bounded? || overlay.bounded?,
615
527
  translates: (base.translates + overlay.translates).uniq
616
528
  )
617
529
  end
618
530
 
619
- # Recovered and generalized — see `add_world`'s own comment. `realm`/
620
- # `latest`, `default_database` and `default_adapter` are scalars, so the overlay's
621
- # value wins when present, else the base's survives; `settings` is a shallow merge keyed by
622
- # verb (and `"verb:adapter"`) — an overlay entry for a key the base
623
- # also declares replaces that key's whole resolved hash (the same
624
- # all-or-nothing shape `WorldBuilder#method_missing` already builds
625
- # each entry as), it does not deep-merge field by field within it.
531
+ # Scalars (`realm`, `latest`, `default_database`, `default_adapter`): the overlay's
532
+ # value wins when present, else the base's survives. `settings` is a shallow merge
533
+ # keyed by verb (and `"verb:adapter"`); an overlay key replaces the base's whole
534
+ # resolved hash for that key, it does not deep-merge within it.
626
535
  #
627
536
  # @param base [Bluebook::World] the domain's already-registered world
628
537
  # @param overlay [Bluebook::World] the newly loaded block's own world to fold in