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
@@ -2,21 +2,8 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # Which value a creating command's own identity field gets, when
6
- # neither a slug-from-another-field nor a sequence-with-prefix
7
- # mechanically answers it — a driving app's own console, say,
8
- # falls back to this when a collection's identity strategy names
9
- # "port" rather than "slug"/"sequence" (both of those stay pure
10
- # config-driven mechanics, computed by whoever is dispatching,
11
- # never by this port).
12
- #
13
- # Pure delegation, same as every sibling port (AccessControl,
14
- # IdentityGeneration): an app's own domain declares what "port"
15
- # actually means for it — mint a real UUID via
16
- # Ports::IdentityGeneration, derive something else entirely — this
17
- # port just resolves the one adapter that domain wired and calls
18
- # it, the same "one adapter registry-wide, refuse if zero or many"
19
- # resolution every other port here already uses.
5
+ # Which value a creating command's identity field gets when its strategy names "port".
6
+ # Delegates to the one adapter the domain wired.
20
7
  module IdentityAssignment
21
8
  NAME = "identity_assignment".freeze
22
9
 
@@ -24,29 +11,21 @@ module Hecks
24
11
 
25
12
  # Asks the domain's adapter which value a creating command's identity field gets.
26
13
  #
27
- # No adapter, spec double or caller of this port ships in this repository, so every
28
- # shape below other than `registry` is adapter-defined: the port forwards it untouched.
14
+ # Every argument other than `registry` is adapter-defined and forwarded untouched.
29
15
  #
30
16
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
31
- # @param agg_name [Object] adapter-defined, forwarded unchanged; names the aggregate
32
- # whose identity field is being assigned
33
- # @param field_name [Object] adapter-defined, forwarded unchanged; names the identity
34
- # field
35
- # @param args [Object] adapter-defined, forwarded unchanged; the creating command's own
36
- # arguments
17
+ # @param agg_name [Object] adapter-defined; names the aggregate being assigned
18
+ # @param field_name [Object] adapter-defined; names the identity field
19
+ # @param args [Object] adapter-defined; the creating command's own arguments
37
20
  # @return [Object] adapter-defined value to assign as the identity
38
21
  # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
39
- # (see `adapter`)
40
22
  def assign(registry, agg_name:, field_name:, args:)
41
23
  adapter(registry).assign(registry, agg_name: agg_name, field_name: field_name, args: args)
42
24
  end
43
25
 
44
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
26
+ # Finds the single adapter bound to this port.
45
27
  #
46
- # @param registry [Runtime::Registry] the booted registry to search
47
- # @return [Module] the adapter module or class implementing this port
48
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
49
- # or the one that does has no Ruby implementation under `Hecks::Adapters`
28
+ # @raise [Runtime::WiringError] if none, or more than one, implements this port
50
29
  def adapter(registry)
51
30
  implementations = registry.adapters.values.select { |a| a.port == NAME }
52
31
 
@@ -2,27 +2,9 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # A creating command with no natural key needs a value from
6
- # somewhere to be its identity — this is that somewhere. Resolved
7
- # the same way `Ports::Extraction` resolves its own adapter (one
8
- # adapter registry-wide implements this port, not a per-aggregate
9
- # binding the way persistence needs — different aggregates have no
10
- # real reason to want different id-generation strategies within
11
- # one running app).
12
- #
13
- # Replay needs no suppression here, on purpose. A UUID minted for a
14
- # creating command's identity gets baked into that step's own args
15
- # — an ordinary string value — the moment it's generated, by
16
- # whoever issues the first, live dispatch. A recorded corpus
17
- # script or a captured fuzz-replay step already holds that
18
- # concrete value; replaying it calls `dispatch` with the same
19
- # args, and this module is never consulted again, for the same
20
- # reason `SecureRandom.uuid` never runs twice for one
21
- # already-recorded step today. `Event#occurred_at`
22
- # (`command_rules/emission.rb`) is the one other "environmental
23
- # fact, not caller-supplied" this codebase has, and it's handled
24
- # the identical way: it fires on every dispatch, replay included,
25
- # and comparison simply excludes it.
5
+ # Supplies the identity for a creating command with no natural key.
6
+ # One adapter registry-wide implements it. Replay never calls it: the minted value is
7
+ # already baked into the recorded step's args.
26
8
  module IdentityGeneration
27
9
  NAME = "identity_generation".freeze
28
10
 
@@ -32,18 +14,13 @@ module Hecks
32
14
  #
33
15
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
34
16
  # @return [String] a newly minted identity: a random UUID from `SecureRandomIdentity`,
35
- # or a decimal counter (`"1"`, `"2"`, …) from the deterministic `SequentialIdentity`
36
- # spec double — unique per adapter, not guaranteed UUID-shaped
17
+ # or a decimal counter from the deterministic `SequentialIdentity` spec double
37
18
  # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
38
- # (see `adapter`)
39
19
  def uuid(registry) = adapter(registry).uuid
40
20
 
41
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
21
+ # Finds the single adapter bound to this port.
42
22
  #
43
- # @param registry [Runtime::Registry] the booted registry to search
44
- # @return [Module] the adapter module or class implementing this port
45
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
46
- # or the one that does has no Ruby implementation under `Hecks::Adapters`
23
+ # @raise [Runtime::WiringError] if none, or more than one, implements this port
47
24
  def adapter(registry)
48
25
  implementations = registry.adapters.values.select { |a| a.port == NAME }
49
26
 
@@ -2,16 +2,8 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # An authenticated (issuer, subject) pair, resolved to the id of a stable
6
- # `Identity` — the other half of the same symmetry `Authorization`
7
- # already has for Governance: one adapter registry-wide answers this
8
- # port, resolved the same zero/one/many way, so an application never
9
- # has to name `Identity` directly to ask "who is this."
10
- #
11
- # Answers `nil` for a pair nothing has linked — the caller decides
12
- # what that means (refuse, prompt to register, whatever), the same
13
- # way `Authorization#holds_role?` answering `false` decides nothing
14
- # on its own.
5
+ # Resolves an authenticated (issuer, subject) pair to a stable identity id.
6
+ # One adapter registry-wide answers this port.
15
7
  module IdentityResolution
16
8
  NAME = "identity_resolution".freeze
17
9
 
@@ -2,55 +2,23 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # A subject's own encryption key lives here, one boundary removed from
6
- # any event or bluebook attribute — cryptoshredding depends on the key
7
- # material never being reachable except through this port's opaque
8
- # reference (see `Privacy::SubjectKey`, `lib/hecks/framework/bluebook/
9
- # privacy.bluebook`). Resolved the same way `Ports::IdentityGeneration`
10
- # resolves its own adapter: one adapter registry-wide answers this
11
- # port, not a per-aggregate binding.
5
+ # A subject's encryption key, one boundary removed from any event or
6
+ # bluebook attribute, so cryptoshredding never exposes key material.
12
7
  module KeyVault
13
8
  NAME = "key_vault".freeze
14
9
 
15
10
  module_function
16
11
 
17
- # Mints a fresh per-subject encryption key and hands back an opaque reference to it.
18
- #
19
- # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
20
- # @param subject_id [String] the data subject the key is being issued for
21
- # @return [String] an opaque key reference; the key material itself never leaves the
22
- # bound adapter, and is never suitable to store on an event or a bluebook attribute
12
+ # Mints a per-subject key; the key material itself never leaves the bound adapter.
23
13
  def issue(registry, subject_id:) = adapter(registry).issue(subject_id: subject_id)
24
14
 
25
- # Irrevocably destroys a key that {#issue} already returned a reference for.
26
- #
27
- # Ciphertext produced under `key_reference` becomes permanently unrecoverable the
28
- # moment this returns — the mechanism a right-to-erasure request satisfies without
29
- # rewriting or deleting any event.
30
- #
31
- # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
32
- # @param key_reference [String] the opaque reference {#issue} returned
33
- # @return [Boolean] true when a live key was destroyed; false when this reference was
34
- # already destroyed, or was never issued
15
+ # Irrevocably destroys a key; ciphertext under it becomes unrecoverable at once —
16
+ # how a right-to-erasure request is satisfied without rewriting or deleting events.
35
17
  def destroy(registry, key_reference:) = adapter(registry).destroy(key_reference: key_reference)
36
18
 
37
- # Erases one subject: destroys their key in the vault, then durably records that it
38
- # happened — in that fixed order, so a caller cannot dispatch `Shred` before the key
39
- # is actually gone the way calling {#destroy} and `dispatch_flat` separately would
40
- # allow. `Privacy::SubjectKey.Shred`'s own lifecycle guard (`from: "active"`) still
41
- # refuses a raw double-dispatch; this is what closes the gap one level up, where the
42
- # danger isn't a duplicate `Shred` but `Shred` running *before* {#destroy} does.
43
- #
44
- # Idempotent: a subject with no live `SubjectKey` record, or one already shredded,
45
- # is left alone and answered `false` — a retried erasure request never re-destroys
46
- # an already-gone key or double-dispatches `Shred`.
47
- #
48
- # @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
49
- # dispatcher both the lookup query and the `Shred` dispatch run through
50
- # @param domain [String] the subject's own domain FQN, e.g. `"Site::Registration"`
51
- # @param subject_id [String] the data subject to erase
52
- # @return [Boolean] true when a live key was found and shredded by this call; false
53
- # when no `SubjectKey` record exists for this subject, or it was already shredded
19
+ # Destroys the subject's key, then dispatches Shred, in that fixed order — never the
20
+ # reverse, so Shred cannot be dispatched before the key is actually gone. Idempotent:
21
+ # a subject with no live key, or one already shredded, is left alone and returns false.
54
22
  def shred!(dispatcher, domain:, subject_id:) # rubocop:disable Naming/PredicateMethod
55
23
  record = dispatcher.query("Privacy::SubjectKey.ForSubject", domain: domain, subject_id: subject_id).first
56
24
  return false unless record
@@ -61,11 +29,7 @@ module Hecks
61
29
  true
62
30
  end
63
31
 
64
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
65
- #
66
- # @param registry [Runtime::Registry] the booted registry to search
67
- # @return [Module] the adapter module or class implementing this port
68
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port
32
+ # Refuses an ambiguous wiring rather than choosing an adapter arbitrarily.
69
33
  def adapter(registry)
70
34
  implementations = registry.adapters.values.select { |a| a.port == NAME }
71
35
 
@@ -6,7 +6,12 @@ module Hecks
6
6
  module Persistence
7
7
  # `mirrors` is durable replication intent. It is part of the same
8
8
  # append as the authoritative state, never a second outbox store.
9
- Entry = Struct.new(:operation, :id, :state, :mirrors, keyword_init: true) do
9
+ #
10
+ # `sequence` is the journal position an adapter assigned this entry
11
+ # (set by `append` on a live write, or by `entries`/`entries_since` on
12
+ # a replayed one); nil for an adapter that assigns none. It rides
13
+ # along so `project` can advance a checkpoint without a second lookup.
14
+ Entry = Struct.new(:operation, :id, :state, :mirrors, :sequence, keyword_init: true) do
10
15
  # Tells a projecting adapter that this entry writes a record.
11
16
  #
12
17
  # @return [Boolean] true when `operation` is the String `"save"`
@@ -18,9 +23,8 @@ module Hecks
18
23
  def delete? = operation == "delete"
19
24
  end
20
25
 
21
- # Makes append-before-projection a port invariant. Adapters retain
22
- # control of their durable format, but every one must accept the same
23
- # entry stream and materialize current state from it.
26
+ # Makes append-before-projection a port invariant: adapters keep their own durable
27
+ # format, but must accept the same entry stream and materialize state from it.
24
28
  class AppendOnly
25
29
  attr_reader :adapter
26
30
 
@@ -71,6 +75,17 @@ module Hecks
71
75
  # undecoded (`CodecBoundary.check_entries!`)
72
76
  def entries = @adapter.entries
73
77
 
78
+ # Reads how far this repository's journal has been compacted, when the adapter tracks
79
+ # that (Postgres, Sqlite).
80
+ #
81
+ # @return [Integer] the highest journal `sequence` already deleted by compaction; 0 for
82
+ # an adapter that tracks no such thing, or nothing compacted yet
83
+ def compacted_through
84
+ return 0 unless @adapter.respond_to?(:compacted_through)
85
+
86
+ @adapter.compacted_through
87
+ end
88
+
74
89
  # Lists the optional persistence behaviours the adapter advertises.
75
90
  #
76
91
  # @return [Array<Symbol>] frozen capability names such as `:atomic_put`,
@@ -96,12 +111,8 @@ module Hecks
96
111
 
97
112
  # Reads the events the adapter has durably recorded.
98
113
  #
99
- # Not an endless `def events = ... if ...` — that modifier binds to
100
- # the whole `def`, not just its body, so it evaluates against
101
- # `@adapter` while `@adapter` is still nil (class-body time,
102
- # before `initialize` ever runs) and silently skips defining the
103
- # method at all. Found live: nothing in this codebase called
104
- # `AppendOnly#events` before Memory got a `reset!` test that did.
114
+ # Written as an `if` guard, not a trailing modifier, which would evaluate against
115
+ # `@adapter` before `initialize` runs and silently skip defining the method.
105
116
  #
106
117
  # @return [Array<Runtime::Event>, nil] recorded events, oldest first; nil when the
107
118
  # adapter keeps no event log
@@ -109,15 +120,39 @@ module Hecks
109
120
  @adapter.events if @adapter.respond_to?(:events)
110
121
  end
111
122
 
112
- # Replays the whole journal through `project` to rebuild the projected records.
123
+ # Reads back one record's durably recorded events, oldest first, scoped by the
124
+ # adapter itself when it can (a SQL adapter pushes this down as a `WHERE` clause
125
+ # instead of `#events`'s whole-table read); falls back to filtering `#events` for
126
+ # an adapter with no scoped lookup of its own.
113
127
  #
114
- # An append is durable before a projection is attempted. Replaying the
115
- # log restores a snapshot/table after a crash in that small window.
128
+ # @param aggregate [String] the `"domain::AggregateName"` key events are stored under
129
+ # @param id [String, Object] the record's identity, matched as `id.to_s`
130
+ # @return [Array<Runtime::Event>, nil] the record's events; nil when the adapter
131
+ # keeps no event log at all
132
+ def events_for(aggregate:, id:)
133
+ return @adapter.events_for(aggregate: aggregate, id: id) if @adapter.respond_to?(:events_for)
134
+
135
+ events&.select { |event| event.aggregate == aggregate && event.id.to_s == id.to_s }
136
+ end
137
+
138
+ # Replays unprojected journal entries through `project` to rebuild the projected records.
139
+ #
140
+ # An append is durable before a projection is attempted; replaying restores a
141
+ # snapshot/table after a crash in that small window. Postgres and Sqlite keep their
142
+ # projected table in the same transaction as the journal append, so they never fall
143
+ # behind it — each tracks how far it has replayed (`checkpoint`) and only re-walks
144
+ # entries past that point (`entries_since`), bounded by activity since the last boot,
145
+ # not total history. An adapter without that pair (Memory, Heki, D1, PostgresEra,
146
+ # RemoteRuntime) is unaffected: it still replays every entry.
116
147
  #
117
148
  # @return [Persistence::AppendOnly] self, so a factory can build and recover in one
118
149
  # expression
119
150
  def recover!
120
- entries.each { |entry| project(entry) }
151
+ if @adapter.respond_to?(:checkpoint) && @adapter.respond_to?(:entries_since)
152
+ @adapter.entries_since(@adapter.checkpoint).each { |entry| project(entry) }
153
+ else
154
+ entries.each { |entry| project(entry) }
155
+ end
121
156
  self
122
157
  end
123
158
 
@@ -142,29 +177,15 @@ module Hecks
142
177
 
143
178
  # Journals an instance's state, projects it, and reports how the write landed.
144
179
  #
145
- # Returns an `Outcome`, not a bare `Instance` — every call site
146
- # (`CommandInterpreter`/`EntityInterpreter`'s own `step_save`,
147
- # `RebuildSweep#refresh`) reads it that way.
148
- #
149
- # `expected_version:` requests optimistic-concurrency CAS — commit
150
- # only if the stored record's version still matches what this
151
- # instance was read at. It is `nil` both when a caller explicitly
152
- # doesn't want CAS (`RebuildSweep#refresh`'s own projection-field
153
- # touch-up, which has no `given` to protect) and when the instance
154
- # is brand new (never read from storage, so `instance.version` is
155
- # nil) — both cases fall through to the plain, unconditional
156
- # `project(entry)` below, byte-for-byte today's behavior. Only an
157
- # adapter that both receives a non-nil `expected_version` and
158
- # declares `:optimistic_concurrency` gets CAS treatment; every
159
- # other adapter/call site is unaffected.
180
+ # Returns an Outcome, not a bare Instance, so callers can check `:saved` vs `:stale`;
181
+ # `expected_version:` only triggers CAS on an adapter declaring `:optimistic_concurrency`.
160
182
  #
161
183
  # @param instance [Runtime::Instance] the record to persist; its `state` is shallow
162
184
  # copied into the entry
163
185
  # @param expected_version [Integer, nil] the version the instance was read at, or nil
164
186
  # for an unconditional write
165
- # @return [Persistence::Outcome] status `:saved` or `:stale`; on `:saved` its `instance`
166
- # is what the adapter's `project` answered, else the instance passed in; on `:stale`
167
- # it is the instance passed in. The entry is journaled even when the result is `:stale`
187
+ # @return [Persistence::Outcome] status `:saved` or `:stale`; `instance` is the
188
+ # adapter's projected result on `:saved`, else the instance passed in
168
189
  # @raise [Runtime::WiringError] when the adapter's `append` or `project` refuses
169
190
  def save(instance, expected_version: nil)
170
191
  entry = Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
@@ -218,18 +239,7 @@ module Hecks
218
239
 
219
240
  # Records one emitted event durably, when the adapter keeps an event log.
220
241
  #
221
- # Not an endless `def record_event = ... if ...` — same gotcha as
222
- # `events` above, and it bit for real here: this guard evaluated
223
- # against `@adapter` at class-body time (nil, always false), so
224
- # `record_event` was never defined at all. `emission.rb`'s own
225
- # `repository.record_event(event) if repository.respond_to?(:record_event)`
226
- # therefore never fired for any adapter, ever — every declared
227
- # `emits` was computed and reported in `registry.event_log` (an
228
- # in-process array, gone at exit) but never durably recorded.
229
- # Caught because a live tail of a domain's own persisted events
230
- # found nothing to tail. `sqlite_spec.rb`/`postgres_spec.rb`/
231
- # `postgres_era_spec.rb` all call `adapter.record_event` directly,
232
- # bypassing this wrapper — which is exactly why no spec noticed.
242
+ # Written as an `if` guard, not a trailing modifier — same reason as `events` above.
233
243
  #
234
244
  # @param event [Runtime::Event] the event to record
235
245
  # @return [Object, nil] adapter-defined write result (an Array for Memory, a driver
@@ -240,17 +250,9 @@ module Hecks
240
250
 
241
251
  # Runs the block inside the adapter's transaction, or plainly when it has none.
242
252
  #
243
- # One COMMIT boundary for save + emit + outbox — `Interpreting#
244
- # run_dispatch_order` runs the `save` and `emit` steps inside
245
- # this block, so an adapter that owns a real transaction
246
- # (Sqlite, Postgres) commits the aggregate row, its journal
247
- # entry, and the outbox rows together or not at all. An adapter
248
- # without one just yields: Memory has nothing to roll back, and
249
- # a file adapter's own `with_lock` already serialises its pair
250
- # of writes. Nested calls are the adapter's problem to make
251
- # re-entrant (both SQL adapters check for an open transaction
252
- # first) — a reaction dispatched from inside a drain never nests
253
- # here anyway, because draining happens after this block returns.
253
+ # One commit boundary for save + emit + outbox: an adapter with a real transaction
254
+ # (Sqlite, Postgres) commits the row, journal entry, and outbox rows together or
255
+ # not at all; Memory just yields, having nothing to roll back.
254
256
  #
255
257
  # @yield the writes to commit together; an exception raised inside rolls back an
256
258
  # adapter-owned transaction and propagates
@@ -264,11 +266,9 @@ module Hecks
264
266
 
265
267
  # Runs the block while holding the adapter's cross-process write lock.
266
268
  #
267
- # Only an adapter advertising `:cross_process_lock` (PostgresEra —
268
- # see ADR 0036) implements this; `run_dispatch_order_with_isolation`
269
- # (runtime/interpreting.rb) checks `capabilities` before ever
270
- # calling it, so the plain `yield` fallback here only guards
271
- # against a stray direct call, not the real dispatch path.
269
+ # Only PostgresEra advertises `:cross_process_lock` (ADR 0036); the real dispatch
270
+ # path checks `capabilities` first, so this `yield` fallback only guards a stray
271
+ # direct call.
272
272
  #
273
273
  # @yield the dispatch to run with writers serialised
274
274
  # @return [Object] adapter-defined; the block's own value when the adapter has no
@@ -279,10 +279,7 @@ module Hecks
279
279
  yield
280
280
  end
281
281
 
282
- # **The outbox contract** — four optional adapter methods, probed
283
- # together the way `save_saga`/`delete_saga`/`each_saga` are
284
- # (`Registry::SagaPersistence`): an adapter either has an outbox
285
- # or it doesn't, never half of one. See `Runtime::Outbox`.
282
+ # An adapter implements the whole outbox contract or none of it (see Runtime::Outbox).
286
283
  OUTBOX_METHODS = %i[outbox_enqueue outbox_claim outbox_settle outbox_rows].freeze
287
284
 
288
285
  # Reports whether the adapter implements the whole outbox contract; the answer is
@@ -4,23 +4,13 @@ require_relative "../../runtime/registry"
4
4
  module Hecks
5
5
  module Ports
6
6
  module Persistence
7
- # Resolves one aggregate's persistence topology. An unmarked binding is
8
- # authoritative; roles are deliberately opt-in so a second adapter can
9
- # never silently become a read source.
7
+ # Resolves one aggregate's persistence topology; an unmarked binding is
8
+ # authoritative, and roles are opt-in so no adapter silently becomes a read source.
10
9
  module BindingPolicy
11
10
  module_function
12
11
 
13
- # Picks the one bind that names an aggregate's authoritative store.
14
- #
15
- # A domain with no hecksagon gets the default in-memory bind. A domain that has one
16
- # must bind the aggregate exactly once without a role.
17
- #
18
- # A `default_adapter` a world declares (`Registry#default_adapter_for` — the
19
- # chapter's own world, else the project's) stands in wherever the hecksagon binds
20
- # nothing for the aggregate, and replaces the in-memory fallback for a domain
21
- # with no hecksagon. It is never consulted once the hecksagon binds the aggregate
22
- # or declares a domain-level default of its own, so an explicit chapter decision
23
- # always wins.
12
+ # Picks the one bind that names an aggregate's authoritative store. A world's
13
+ # `default_adapter` only fills a hecksagon's gap; an explicit bind always wins.
24
14
  #
25
15
  # @param registry [Runtime::Registry] the registry holding the domain's hecksagon
26
16
  # @param domain [String, Symbol] name of the domain the aggregate belongs to
@@ -4,47 +4,15 @@ require_relative "../../runtime/errors"
4
4
  module Hecks
5
5
  module Ports
6
6
  module Persistence
7
- # No adapter can build an `Instance` from undecoded state (Phase 2,
8
- # Track A, PR A3). Routing every adapter through `StateCodec` is a
9
- # convention until something refuses the bypass; this is that
10
- # something, and it is installed by `RepositoryFactory.build` — the
11
- # one place every runtime repository is made — so no adapter can opt
12
- # out of it.
13
- #
14
- # ## The mechanism, two halves
15
- #
16
- # 1. `guard!(adapter)` extends the adapter object (not its class,
17
- # not a proxy — `is_a?`, `class`, and `===` stay the adapter's
18
- # own) with a module that wraps every public method the adapter's
19
- # class defines. Each call runs inside the boundary: a
20
- # thread-local flag, re-entrant, restored on the way out. A block
21
- # the caller passes (`transaction`, `with_write_lock`,
22
- # `each_saga`) runs outside it — that block is the dispatch
23
- # itself (hydrate, entity views, mutation), not adapter code.
24
- # Reaching the adapter through `repository.adapter` (the query
25
- # port, saga persistence, `bin/heki_compact`) is guarded all the
26
- # same: the wrapper is on the object.
27
- #
28
- # 2. `Runtime::Instance#initialize` asks `check_state!` whenever it
29
- # is handed `state:`. Outside the boundary that is a no-op; inside
30
- # it, state `StateCodec.decoded?` rejects refuses by name. An
31
- # `entries` answer is checked the same way on its way out, since a
32
- # journal `Entry` is not an `Instance`.
33
- #
34
- # ## Checked, not silently decoded
35
- #
36
- # An adapter that forgets the codec is a bug in that adapter, and
37
- # decoding for it here would hide the forgetting. Hydration does not
38
- # respell keys either (A4) — `Value.hydrate` refuses a non-Symbol
39
- # top-level key everywhere — so this boundary's deep check and
40
- # hydration's shallow one agree.
7
+ # Refuses to let a guarded adapter build an `Instance` from undecoded state.
8
+ # `RepositoryFactory.build` installs it, so no adapter can opt out.
41
9
  module CodecBoundary
42
10
  KEY = :hecks_persistence_codec_boundary
43
11
 
44
12
  module_function
45
13
 
46
- # Extends an adapter object so every public method its class defines runs inside the
47
- # boundary; guarding an adapter twice wraps it once.
14
+ # Extends the adapter object so every public method its class defines runs inside the
15
+ # boundary; guarding twice wraps once.
48
16
  #
49
17
  # @param adapter [Object] a driven persistence adapter instance
50
18
  # @return [Object] the same adapter object, now including `Guarded`
@@ -53,33 +21,22 @@ module Hecks
53
21
  adapter
54
22
  end
55
23
 
56
- # Reports whether the current thread is executing inside a guarded adapter call.
24
+ # Whether this thread is currently inside a guarded adapter call.
57
25
  #
58
- # @return [Boolean] true between entering a guarded adapter method and yielding to the
59
- # caller's block or returning
26
+ # @return [Boolean]
60
27
  def active? = Thread.current[KEY] == true
61
28
 
62
- # Runs the block with the boundary switched on for this thread, restoring the earlier
63
- # setting afterwards.
64
- #
65
- # @yield adapter code whose `Instance` construction is to be checked
66
- # @return [Object] the block's value
29
+ # Runs the block with the boundary on for this thread; re-entrant.
67
30
  def within(&) = with_flag(true, &)
68
31
 
69
- # Runs the block with the boundary switched off for this thread, restoring the earlier
70
- # setting afterwards.
71
- #
72
- # @yield caller code, such as a dispatch running inside the adapter's transaction
73
- # @return [Object] the block's value
32
+ # Runs the block with the boundary off for this thread; re-entrant.
74
33
  def outside(&) = with_flag(false, &)
75
34
 
76
- # Refuses state an adapter is about to build an `Instance` from unless it is decoded;
77
- # outside the boundary it checks nothing.
35
+ # Refuses undecoded state headed for `Runtime::Instance.new`; a no-op outside the boundary.
78
36
  #
79
37
  # @param aggregate [Bluebook::Aggregate, Bluebook::Entity] the construct the state
80
38
  # belongs to
81
39
  # @param state [Hash, Runtime::Value] the state handed to `Runtime::Instance.new`
82
- # @return [nil] when the boundary is inactive or the state is decoded
83
40
  # @raise [Runtime::WiringError] if the boundary is active and
84
41
  # `StateCodec.decoded?` rejects the state
85
42
  def check_state!(aggregate, state)
@@ -93,13 +50,12 @@ module Hecks
93
50
  end
94
51
 
95
52
  # Refuses a guarded adapter's `entries` answer if any entry's state is undecoded.
53
+ # A journal `Entry` is not an `Instance`, so `check_state!` never sees it.
96
54
  #
97
- # @param adapter [Object] the guarded adapter, asked for its `aggregate` and class name
98
- # @param entries [Array<Persistence::Entry>, Object] what the adapter's `entries`
99
- # returned; anything that is not an Array passes through unchecked
55
+ # @param adapter [Object] the guarded adapter
56
+ # @param entries [Array<Persistence::Entry>, Object] anything but an Array passes unchecked
100
57
  # @return [Array<Persistence::Entry>, Object] `entries` itself
101
- # @raise [Runtime::WiringError] if an `Entry` in the Array carries state
102
- # `StateCodec.decoded?` rejects
58
+ # @raise [Runtime::WiringError] if an `Entry` carries state `StateCodec.decoded?` rejects
103
59
  def check_entries!(adapter, entries)
104
60
  return entries unless entries.is_a?(Array)
105
61
 
@@ -113,13 +69,7 @@ module Hecks
113
69
  entries
114
70
  end
115
71
 
116
- # Sets the thread-local boundary flag for the length of the block, which is what makes
117
- # the boundary re-entrant.
118
- #
119
- # @param value [Boolean] true to switch the boundary on, false to switch it off
120
- # @yield the code to run under that setting
121
- # @return [Object] the block's value; the earlier flag is restored even when the
122
- # block raises
72
+ # Sets the thread-local flag for the block and restores it after, even on a raise.
123
73
  def with_flag(value)
124
74
  previous = Thread.current[KEY]
125
75
  Thread.current[KEY] = value
@@ -128,24 +78,18 @@ module Hecks
128
78
  Thread.current[KEY] = previous
129
79
  end
130
80
 
131
- # Marks a guarded adapter so a second `guard!` (a projection and an
132
- # authoritative repository built over one object) never wraps twice.
81
+ # Marks a guarded adapter so a second `guard!` never wraps it twice.
133
82
  module Guarded; end
134
83
 
135
- # Filled lazily under `WRAPPERS_LOCK`, one entry per adapter class —
136
- # a cache, deliberately mutable.
84
+ # A per-adapter-class cache, filled lazily under `WRAPPERS_LOCK`; deliberately mutable.
137
85
  WRAPPERS = {} # rubocop:disable Style/MutableConstant
138
86
  WRAPPERS_LOCK = Mutex.new
139
87
 
140
88
  # Builds, or fetches from the cache, the module that guards one adapter class.
141
- #
142
- # One wrapper module per adapter class, built once: every public
143
- # instance method the class (and its ancestors below Object)
144
- # defines, each forwarding to `super` inside the boundary.
89
+ # Each public method forwards to `super` inside the boundary.
145
90
  #
146
91
  # @param klass [Class] the adapter's class
147
- # @return [Module] an anonymous module including `Guarded`, meant to be `extend`ed onto
148
- # instances of `klass`
92
+ # @return [Module] an anonymous module including `Guarded`, to `extend` onto instances
149
93
  def wrapper_for(klass)
150
94
  WRAPPERS_LOCK.synchronize do
151
95
  WRAPPERS[klass] ||= Module.new do
@@ -161,12 +105,8 @@ module Hecks
161
105
  end
162
106
  end
163
107
 
164
- # Wraps the caller's own block so it runs outside the boundary
165
- # whenever the adapter yields to it.
166
- #
167
- # @param block [Proc, nil] the block the caller passed to the adapter method
168
- # @return [Proc, nil] a proc forwarding its arguments to `block` under `outside`; nil
169
- # when no block was given
108
+ # Wraps the caller's block so it runs outside the boundary when the adapter yields to it;
109
+ # that block is the dispatch itself, not adapter code.
170
110
  def outside_block(block)
171
111
  return nil unless block
172
112