hecks 2.8.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (886) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +50 -7
  3. data/lib/hecks/adapters/driven/claude_code.rb +4 -104
  4. data/lib/hecks/adapters/driven/d1.rb +44 -237
  5. data/lib/hecks/adapters/driven/folder.rb +17 -76
  6. data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
  7. data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
  8. data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
  9. data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
  10. data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
  11. data/lib/hecks/adapters/driven/heki.rb +13 -42
  12. data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
  15. data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
  16. data/lib/hecks/adapters/driven/lambda.rb +10 -84
  17. data/lib/hecks/adapters/driven/local_storage.rb +5 -40
  18. data/lib/hecks/adapters/driven/memory.rb +32 -100
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +10 -32
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres/shared_connection.rb +180 -0
  25. data/lib/hecks/adapters/driven/postgres.rb +149 -136
  26. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  27. data/lib/hecks/adapters/driven/prism.rb +48 -38
  28. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  29. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  30. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  31. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  32. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  33. data/lib/hecks/adapters/driven/tenant_provisioner.rb +76 -62
  34. data/lib/hecks/adapters/driven.rb +5 -36
  35. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  36. data/lib/hecks/behaviors/dsl.rb +7 -25
  37. data/lib/hecks/behaviors/expectations.rb +32 -142
  38. data/lib/hecks/behaviors/ir.rb +7 -20
  39. data/lib/hecks/behaviors/rspec.rb +6 -17
  40. data/lib/hecks/behaviors/runner.rb +10 -34
  41. data/lib/hecks/behaviors.rb +4 -8
  42. data/lib/hecks/bench/cli.rb +62 -0
  43. data/lib/hecks/bench/environment.rb +71 -0
  44. data/lib/hecks/bench/postgres_probe.rb +30 -0
  45. data/lib/hecks/bench/report.rb +76 -0
  46. data/lib/hecks/bench/ruby_runner.rb +93 -0
  47. data/lib/hecks/bench/run.rb +55 -0
  48. data/lib/hecks/bench/rust_runner.rb +101 -0
  49. data/lib/hecks/bench/stats.rb +46 -0
  50. data/lib/hecks/bench/suite.rb +98 -0
  51. data/lib/hecks/bench/workload.rb +89 -0
  52. data/lib/hecks/bench.rb +17 -0
  53. data/lib/hecks/bluebook/aggregate.rb +9 -75
  54. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  55. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  56. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  57. data/lib/hecks/bluebook/assembly/contracts.rb +56 -174
  58. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  59. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  60. data/lib/hecks/bluebook/assembly.rb +6 -45
  61. data/lib/hecks/bluebook/attribute.rb +12 -61
  62. data/lib/hecks/bluebook/behaviour/aggregate.rb +39 -39
  63. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  64. data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
  65. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  66. data/lib/hecks/bluebook/behaviour/domain_port.rb +11 -20
  67. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  68. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  69. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  70. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  71. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
  73. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  74. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  75. data/lib/hecks/bluebook/capabilities.rb +17 -49
  76. data/lib/hecks/bluebook/chapter.rb +16 -50
  77. data/lib/hecks/bluebook/command.rb +23 -81
  78. data/lib/hecks/bluebook/domain_port.rb +49 -67
  79. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  80. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  81. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  82. data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
  83. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +96 -708
  84. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +63 -169
  85. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +3 -1
  86. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  87. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  88. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +42 -89
  89. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  90. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  91. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +148 -197
  92. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  93. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  94. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  95. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  96. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  97. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  98. data/lib/hecks/bluebook/dsl/query_builder.rb +38 -43
  99. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  100. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  101. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  102. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  103. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  104. data/lib/hecks/bluebook/dsl/world_builder.rb +46 -111
  105. data/lib/hecks/bluebook/entity.rb +13 -71
  106. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  107. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  108. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  109. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  110. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  111. data/lib/hecks/bluebook/expression/resolver.rb +39 -661
  112. data/lib/hecks/bluebook/hexagon.rb +18 -33
  113. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  114. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  115. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  116. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  117. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  118. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  119. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +25 -176
  120. data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
  121. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -306
  122. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  123. data/lib/hecks/bluebook/meta_validator/verdict_cache.rb +246 -0
  124. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  125. data/lib/hecks/bluebook/meta_validator.rb +87 -352
  126. data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
  127. data/lib/hecks/bluebook/model_check.rb +122 -596
  128. data/lib/hecks/bluebook/pattern_subset.rb +49 -69
  129. data/lib/hecks/bluebook/process_manager.rb +13 -83
  130. data/lib/hecks/bluebook/project_loader.rb +3 -39
  131. data/lib/hecks/bluebook/project_register.rb +12 -60
  132. data/lib/hecks/bluebook/query.rb +27 -51
  133. data/lib/hecks/bluebook/read_model.rb +57 -81
  134. data/lib/hecks/bluebook/reference.rb +7 -41
  135. data/lib/hecks/bluebook/smoke_test.rb +9 -99
  136. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  137. data/lib/hecks/bluebook/translation.rb +26 -62
  138. data/lib/hecks/bluebook/value_object.rb +11 -36
  139. data/lib/hecks/bluebook.rb +5 -22
  140. data/lib/hecks/cache_dir.rb +4 -23
  141. data/lib/hecks/canonical_json.rb +30 -0
  142. data/lib/hecks/chapters.rb +102 -0
  143. data/lib/hecks/cli/behaviors.rb +61 -0
  144. data/lib/hecks/cli/canonicalise.rb +25 -0
  145. data/lib/hecks/cli/check_engine_agreement.rb +32 -0
  146. data/lib/hecks/cli/check_era.rb +88 -0
  147. data/lib/hecks/cli/console.rb +66 -0
  148. data/lib/hecks/cli/deploy_template_diff.rb +40 -0
  149. data/lib/hecks/cli/doc_coverage.rb +32 -0
  150. data/lib/hecks/cli/document.rb +5 -23
  151. data/lib/hecks/cli/expression_projection.rb +41 -0
  152. data/lib/hecks/cli/follow.rb +88 -0
  153. data/lib/hecks/cli/history.rb +44 -0
  154. data/lib/hecks/cli/ir.rb +4 -6
  155. data/lib/hecks/cli/mcp.rb +5 -6
  156. data/lib/hecks/cli/model_check.rb +24 -88
  157. data/lib/hecks/cli/pattern_cases.rb +47 -0
  158. data/lib/hecks/cli/present.rb +39 -0
  159. data/lib/hecks/cli/project_cli.rb +223 -64
  160. data/lib/hecks/cli/project_diagrams.rb +4 -10
  161. data/lib/hecks/cli/project_glossary.rb +44 -0
  162. data/lib/hecks/cli/reference.rb +46 -0
  163. data/lib/hecks/cli/refresh_projections.rb +44 -0
  164. data/lib/hecks/cli/refresh_rspec_runtime_baseline.rb +150 -0
  165. data/lib/hecks/cli/release.rb +70 -0
  166. data/lib/hecks/cli/release_gem.rb +59 -0
  167. data/lib/hecks/cli/rspec_io_parallel_files.rb +137 -0
  168. data/lib/hecks/cli/rspec_shard_files.rb +66 -0
  169. data/lib/hecks/cli/run.rb +15 -61
  170. data/lib/hecks/cli/seed_semantics_corpus.rb +71 -0
  171. data/lib/hecks/cli/serve_query_ir_mcp.rb +30 -0
  172. data/lib/hecks/cli/shape.rb +70 -0
  173. data/lib/hecks/cli/smoke_http.rb +230 -0
  174. data/lib/hecks/cli/smoke_test.rb +7 -19
  175. data/lib/hecks/cli/spec_example.rb +27 -0
  176. data/lib/hecks/cli/statements.rb +32 -0
  177. data/lib/hecks/cli/stores.rb +4 -6
  178. data/lib/hecks/cli/stress_concurrency_specs.rb +177 -0
  179. data/lib/hecks/cli.rb +216 -73
  180. data/lib/hecks/codemod.rb +324 -0
  181. data/lib/hecks/construct.rb +8 -34
  182. data/lib/hecks/corpus.rb +423 -0
  183. data/lib/hecks/deploy/bluebook/deploy.bluebook +617 -158
  184. data/lib/hecks/deploy/bluebook/deploy.hecksagon +41 -11
  185. data/lib/hecks/deploy/oidc.json +82 -2
  186. data/lib/hecks/doc/reference.rb +351 -0
  187. data/lib/hecks/doors/cli_door.rb +196 -0
  188. data/lib/hecks/doors/cli_runner.rb +297 -0
  189. data/lib/hecks/{facade → doors}/command_request.rb +14 -34
  190. data/lib/hecks/doors/handle.rb +206 -0
  191. data/lib/hecks/doors/json_door.rb +132 -0
  192. data/lib/hecks/doors/launcher_options.rb +129 -0
  193. data/lib/hecks/{cli → doors}/mcp_door.rb +25 -120
  194. data/lib/hecks/doors/mcp_door_scope.rb +97 -0
  195. data/lib/hecks/doors/ruby_door/aggregate_door.rb +162 -0
  196. data/lib/hecks/doors/ruby_door/chapter.rb +72 -0
  197. data/lib/hecks/doors/ruby_door.rb +77 -0
  198. data/lib/hecks/doors.rb +61 -0
  199. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  200. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  201. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  202. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  203. data/lib/hecks/embryonaut_bluebook.rb +5 -72
  204. data/lib/hecks/engine_agreement.rb +156 -0
  205. data/lib/hecks/facade.rb +23 -51
  206. data/lib/hecks/forms/app.rb +21 -76
  207. data/lib/hecks/forms/banking_presentation.rb +50 -0
  208. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  209. data/lib/hecks/forms/field_renderer.rb +17 -156
  210. data/lib/hecks/forms/field_shape.rb +31 -222
  211. data/lib/hecks/forms/html.rb +12 -47
  212. data/lib/hecks/forms/index_renderer.rb +1 -4
  213. data/lib/hecks/forms/page.rb +3 -9
  214. data/lib/hecks/forms/params.rb +14 -60
  215. data/lib/hecks/forms/port_argument.rb +2 -19
  216. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  217. data/lib/hecks/forms/record_renderer.rb +8 -75
  218. data/lib/hecks/forms/record_table.rb +7 -50
  219. data/lib/hecks/forms/reference_options.rb +3 -30
  220. data/lib/hecks/forms/value_object_shape.rb +8 -35
  221. data/lib/hecks/forms.rb +5 -33
  222. data/lib/hecks/fqn.rb +5 -12
  223. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  224. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  225. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  226. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  227. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  228. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  229. data/lib/hecks/framework.rb +11 -80
  230. data/lib/hecks/freezer.rb +5 -39
  231. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +393 -0
  232. data/lib/hecks/fuzzing/combination_miner.rb +86 -0
  233. data/lib/hecks/fuzzing/concurrent_dispatch.rb +214 -0
  234. data/lib/hecks/fuzzing/coverage_campaign.rb +143 -0
  235. data/lib/hecks/fuzzing/differential.rb +156 -0
  236. data/lib/hecks/fuzzing/domain_generator.rb +615 -0
  237. data/lib/hecks/fuzzing/era_boundary.rb +71 -0
  238. data/lib/hecks/fuzzing/form_census.rb +136 -0
  239. data/lib/hecks/fuzzing/generated_domain_check.rb +93 -0
  240. data/lib/hecks/fuzzing/invalid_value_generator.rb +64 -0
  241. data/lib/hecks/fuzzing/isolated_boot.rb +301 -0
  242. data/lib/hecks/fuzzing/nondeterministic.rb +51 -0
  243. data/lib/hecks/fuzzing/outside_world.rb +45 -0
  244. data/lib/hecks/fuzzing/persistence_parity.rb +102 -0
  245. data/lib/hecks/fuzzing/properties/corrections.rb +88 -0
  246. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +314 -0
  247. data/lib/hecks/fuzzing/properties/guards.rb +190 -0
  248. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +300 -0
  249. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +93 -0
  250. data/lib/hecks/fuzzing/properties/outbox.rb +89 -0
  251. data/lib/hecks/fuzzing/properties/querying.rb +175 -0
  252. data/lib/hecks/fuzzing/properties.rb +162 -0
  253. data/lib/hecks/fuzzing/qa_settings.rb +123 -0
  254. data/lib/hecks/fuzzing/replay.rb +505 -0
  255. data/lib/hecks/fuzzing/rotation_priority.rb +48 -0
  256. data/lib/hecks/fuzzing/rust_gap_manifest.rb +108 -0
  257. data/lib/hecks/fuzzing/self_consistency.rb +339 -0
  258. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +385 -0
  259. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +132 -0
  260. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +95 -0
  261. data/lib/hecks/fuzzing/sequence_generator/picker.rb +77 -0
  262. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +109 -0
  263. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +237 -0
  264. data/lib/hecks/fuzzing/sequence_generator.rb +189 -0
  265. data/lib/hecks/fuzzing/shrinker.rb +166 -0
  266. data/lib/hecks/fuzzing/structural_skips.rb +33 -0
  267. data/lib/hecks/fuzzing/sweep_depth.rb +43 -0
  268. data/lib/hecks/fuzzing/target_capabilities.rb +163 -0
  269. data/lib/hecks/fuzzing/value_generator.rb +216 -0
  270. data/lib/hecks/fuzzing.rb +23 -0
  271. data/lib/hecks/grammar/evolve.rb +336 -0
  272. data/lib/hecks/grammar/expression.bluebook +15 -40
  273. data/lib/hecks/grammar/translation.bluebook +3 -6
  274. data/lib/hecks/grammar.rb +16 -41
  275. data/lib/hecks/hecks/adapters/codebase/codemods.rb +45 -0
  276. data/lib/hecks/hecks/adapters/codebase/conformance.rb +71 -0
  277. data/lib/hecks/hecks/adapters/codebase/corpus_tasks.rb +202 -0
  278. data/lib/hecks/hecks/adapters/codebase/gem_registry.rb +80 -0
  279. data/lib/hecks/hecks/adapters/codebase/kernel_tables.rb +54 -0
  280. data/lib/hecks/hecks/adapters/codebase/language.rb +240 -0
  281. data/lib/hecks/hecks/adapters/codebase/npm_registry.rb +102 -0
  282. data/lib/hecks/hecks/adapters/codebase/publishing.rb +142 -0
  283. data/lib/hecks/hecks/adapters/codebase/regeneration.rb +67 -0
  284. data/lib/hecks/hecks/adapters/codebase/release_facts.rb +90 -0
  285. data/lib/hecks/hecks/adapters/codebase/ruby_child.rb +83 -0
  286. data/lib/hecks/hecks/adapters/codebase/secret_vault.rb +36 -0
  287. data/lib/hecks/hecks/adapters/codebase/source_tree.adapter +7 -0
  288. data/lib/hecks/hecks/adapters/codebase/source_tree.rb +189 -0
  289. data/lib/hecks/hecks/adapters/codebase/sqlite_fixture.rb +71 -0
  290. data/lib/hecks/hecks/adapters/codebase/style.rb +171 -0
  291. data/lib/hecks/hecks/adapters/codebase/test_runner.rb +55 -0
  292. data/lib/hecks/hecks/adapters/codebase/test_suite.rb +165 -0
  293. data/lib/hecks/hecks/adapters/codebase/tree.rb +111 -0
  294. data/lib/hecks/hecks/adapters/console_capture.rb +79 -0
  295. data/lib/hecks/hecks/adapters/deploy_toolchain.adapter +7 -0
  296. data/lib/hecks/hecks/adapters/deploy_toolchain.rb +108 -0
  297. data/lib/hecks/hecks/adapters/git.adapter +7 -0
  298. data/lib/hecks/hecks/adapters/git.rb +102 -0
  299. data/lib/hecks/hecks/adapters/host_http.adapter +7 -0
  300. data/lib/hecks/hecks/adapters/host_http.rb +65 -0
  301. data/lib/hecks/hecks/adapters/in_process_boot.adapter +7 -0
  302. data/lib/hecks/hecks/adapters/in_process_boot.rb +197 -0
  303. data/lib/hecks/hecks/adapters/in_process_operations.rb +202 -0
  304. data/lib/hecks/hecks/adapters/journal_store/changes.rb +143 -0
  305. data/lib/hecks/hecks/adapters/journal_store/compaction.rb +145 -0
  306. data/lib/hecks/hecks/adapters/journal_store/edge_audit.rb +132 -0
  307. data/lib/hecks/hecks/adapters/journal_store/examination.rb +135 -0
  308. data/lib/hecks/hecks/adapters/journal_store/held_domain.rb +163 -0
  309. data/lib/hecks/hecks/adapters/journal_store/readings.rb +187 -0
  310. data/lib/hecks/hecks/adapters/journal_store.adapter +7 -0
  311. data/lib/hecks/hecks/adapters/journal_store.rb +64 -0
  312. data/lib/hecks/hecks/adapters/local_files.adapter +7 -0
  313. data/lib/hecks/hecks/adapters/local_files.rb +46 -0
  314. data/lib/hecks/hecks/adapters/pg_admin.adapter +7 -0
  315. data/lib/hecks/hecks/adapters/pg_admin.rb +245 -0
  316. data/lib/hecks/hecks/adapters/process_pool.adapter +7 -0
  317. data/lib/hecks/hecks/adapters/process_pool.rb +119 -0
  318. data/lib/hecks/hecks/adapters/rust_toolchain.adapter +7 -0
  319. data/lib/hecks/hecks/adapters/rust_toolchain.rb +179 -0
  320. data/lib/hecks/hecks/adapters/rust_workspace.rb +150 -0
  321. data/lib/hecks/hecks/adapters/shell.adapter +7 -0
  322. data/lib/hecks/hecks/adapters/shell.rb +49 -0
  323. data/lib/hecks/hecks/adapters/terminal.adapter +7 -0
  324. data/lib/hecks/hecks/adapters/terminal.rb +74 -0
  325. data/lib/hecks/hecks/codebase.behaviors +172 -0
  326. data/lib/hecks/hecks/codebase.bluebook +2453 -0
  327. data/lib/hecks/hecks/context_map.hecksagon +13 -0
  328. data/lib/hecks/hecks/custodian.behaviors +179 -0
  329. data/lib/hecks/hecks/custodian.bluebook +1847 -0
  330. data/lib/hecks/hecks/deploy.behaviors +74 -0
  331. data/lib/hecks/hecks/deploy.world +12 -0
  332. data/lib/hecks/hecks/environments/memory.world +10 -0
  333. data/lib/hecks/hecks/governance.world +7 -0
  334. data/lib/hecks/hecks/hecks.behaviors +62 -0
  335. data/lib/hecks/hecks/hecks.bluebook +124 -0
  336. data/lib/hecks/hecks/hecks.hecksagon +390 -0
  337. data/lib/hecks/hecks/hecks.world +42 -0
  338. data/lib/hecks/ir.rb +14 -83
  339. data/lib/hecks/kernel_capabilities.rb +194 -0
  340. data/lib/hecks/language/adapter.bluebook +2 -7
  341. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  342. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  343. data/lib/hecks/language/bluebook/bluebook.bluebook +26 -83
  344. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  345. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  346. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  347. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  348. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  349. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  350. data/lib/hecks/language/bluebook/query.bluebook +19 -43
  351. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  352. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  353. data/lib/hecks/language/bluebook/vocabulary.bluebook +83 -198
  354. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  355. data/lib/hecks/language/hecksagon/domain_port.bluebook +14 -19
  356. data/lib/hecks/language/hecksagon/hecksagon.bluebook +26 -25
  357. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  358. data/lib/hecks/language/oidc.json +35 -0
  359. data/lib/hecks/language/port.bluebook +4 -17
  360. data/lib/hecks/language/translation/translation.bluebook +3 -9
  361. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  362. data/lib/hecks/language/world/wiring.bluebook +1 -3
  363. data/lib/hecks/language/world/world.bluebook +5 -7
  364. data/lib/hecks/literal.rb +8 -50
  365. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  366. data/lib/hecks/naming.rb +29 -137
  367. data/lib/hecks/persistence_legacy_fixture/regenerate.rb +161 -0
  368. data/lib/hecks/persistence_legacy_fixture.rb +113 -0
  369. data/lib/hecks/ports/access_control.rb +7 -23
  370. data/lib/hecks/ports/agent/answers.rb +5 -23
  371. data/lib/hecks/ports/agent.rb +47 -172
  372. data/lib/hecks/ports/authentication.rb +12 -39
  373. data/lib/hecks/ports/authorization.rb +16 -43
  374. data/lib/hecks/ports/clock.rb +5 -45
  375. data/lib/hecks/ports/extraction.rb +7 -12
  376. data/lib/hecks/ports/identity_assignment.rb +8 -29
  377. data/lib/hecks/ports/identity_generation.rb +6 -29
  378. data/lib/hecks/ports/identity_resolution.rb +2 -10
  379. data/lib/hecks/ports/key_vault.rb +9 -45
  380. data/lib/hecks/ports/persistence/append_only.rb +61 -64
  381. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  382. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  383. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  384. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  385. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +44 -144
  386. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  387. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +20 -85
  388. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
  389. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +18 -24
  390. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  391. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  392. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  393. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  394. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  395. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  396. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  397. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  398. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +19 -76
  399. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  400. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  401. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  402. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  403. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  404. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +43 -127
  405. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  406. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +131 -555
  407. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  408. data/lib/hecks/ports/persistence/plugins/era/translation/approval_file.rb +227 -0
  409. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  410. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  411. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  412. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  413. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  414. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +50 -47
  415. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
  416. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  417. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  418. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  419. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  420. data/lib/hecks/ports/persistence/plugins/era/translation.rb +1 -0
  421. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  422. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  423. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  424. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  425. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  426. data/lib/hecks/ports/persistence/state_codec.rb +47 -108
  427. data/lib/hecks/ports/persistence.rb +7 -14
  428. data/lib/hecks/ports/projection.rb +42 -84
  429. data/lib/hecks/ports/query/in_memory.rb +10 -58
  430. data/lib/hecks/ports/query/ordering.rb +11 -32
  431. data/lib/hecks/ports/query.rb +14 -37
  432. data/lib/hecks/ports.rb +2 -8
  433. data/lib/hecks/projection_files.rb +285 -0
  434. data/lib/hecks/projections/bootstrap_table.rb +12 -44
  435. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  436. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  437. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  438. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  439. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  440. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  441. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  442. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  443. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  444. data/lib/hecks/projections/deploy/fargate.rb +40 -207
  445. data/lib/hecks/projections/deploy/lambda.rb +191 -708
  446. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  447. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  448. data/lib/hecks/projections/deploy/preview/preview.sh.erb +1 -1
  449. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  450. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  451. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  452. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  453. data/lib/hecks/projections/deploy/preview/template.rb +3 -59
  454. data/lib/hecks/projections/deploy/preview.rb +2 -67
  455. data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +1 -1
  456. data/lib/hecks/projections/deploy/scripts/expected-era.header +1 -1
  457. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +3 -3
  458. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  459. data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +1 -1
  460. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  461. data/lib/hecks/projections/deploy/shared.rb +48 -147
  462. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  463. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  464. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  465. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  466. data/lib/hecks/projections/diagrams.rb +22 -584
  467. data/lib/hecks/projections/glossary/html.rb +14 -130
  468. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  469. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  470. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  471. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  472. data/lib/hecks/projections/glossary.rb +30 -222
  473. data/lib/hecks/projections/ir.rb +3 -10
  474. data/lib/hecks/projections/model/deviations.rb +16 -43
  475. data/lib/hecks/projections/model.rb +12 -51
  476. data/lib/hecks/projections/oidc.rb +12 -56
  477. data/lib/hecks/projections/parser_table.rb +13 -32
  478. data/lib/hecks/projections/reference.rb +4 -18
  479. data/lib/hecks/projections/rust_vocabulary.rb +13 -251
  480. data/lib/hecks/projections/shape.rb +3 -29
  481. data/lib/hecks/projections/statements.rb +7 -86
  482. data/lib/hecks/projections/vocabulary.rb +6 -22
  483. data/lib/hecks/projections.rb +2 -16
  484. data/lib/hecks/projector/cli_projector.rb +154 -400
  485. data/lib/hecks/projector/docs_projector.rb +10 -201
  486. data/lib/hecks/projector/exporter.rb +42 -134
  487. data/lib/hecks/projector/ir_projector.rb +2 -9
  488. data/lib/hecks/projector/narrate_projector.rb +15 -189
  489. data/lib/hecks/projector/target.rb +13 -76
  490. data/lib/hecks/projector.rb +30 -121
  491. data/lib/hecks/quality_control/adapters/agent.adapter +7 -0
  492. data/lib/hecks/quality_control/adapters/agent.rb +58 -0
  493. data/lib/hecks/quality_control/adapters/angle_tools.adapter +7 -0
  494. data/lib/hecks/quality_control/adapters/angle_tools.rb +15 -0
  495. data/lib/hecks/quality_control/adapters/clearance_recorder.rb +36 -0
  496. data/lib/hecks/quality_control/adapters/clearance_tools.adapter +7 -0
  497. data/lib/hecks/quality_control/adapters/clearance_tools.rb +17 -0
  498. data/lib/hecks/quality_control/adapters/git_pr.adapter +7 -0
  499. data/lib/hecks/quality_control/adapters/git_pr.rb +226 -0
  500. data/lib/hecks/quality_control/adapters/github_checks.adapter +9 -0
  501. data/lib/hecks/quality_control/adapters/github_checks.rb +83 -0
  502. data/lib/hecks/quality_control/adapters/github_ci_webhook.rb +56 -0
  503. data/lib/hecks/quality_control/adapters/github_issues.adapter +7 -0
  504. data/lib/hecks/quality_control/adapters/github_issues.rb +49 -0
  505. data/lib/hecks/quality_control/adapters/qa_tool.rb +59 -0
  506. data/lib/hecks/quality_control/adapters/sweep_tools.adapter +7 -0
  507. data/lib/hecks/quality_control/adapters/sweep_tools.rb +51 -0
  508. data/lib/hecks/quality_control/adapters/target_tools.adapter +7 -0
  509. data/lib/hecks/quality_control/adapters/target_tools.rb +43 -0
  510. data/lib/hecks/quality_control/cli/child.rb +45 -0
  511. data/lib/hecks/quality_control/cli/qa_concurrency_racer.rb +45 -0
  512. data/lib/hecks/quality_control/cli/qa_discover_external_domains.rb +248 -0
  513. data/lib/hecks/quality_control/cli/qa_domain_novelty.rb +163 -0
  514. data/lib/hecks/quality_control/cli/qa_generated_domains.rb +450 -0
  515. data/lib/hecks/quality_control/cli/qa_log_bug.rb +195 -0
  516. data/lib/hecks/quality_control/cli/qa_mine_combinations.rb +220 -0
  517. data/lib/hecks/quality_control/cli/qa_open_pr.rb +305 -0
  518. data/lib/hecks/quality_control/cli/qa_postgres_migrate.rb +154 -0
  519. data/lib/hecks/quality_control/cli/qa_postgres_role.rb +159 -0
  520. data/lib/hecks/quality_control/cli/qa_pr_check.rb +232 -0
  521. data/lib/hecks/quality_control/cli/qa_seed_angles.rb +142 -0
  522. data/lib/hecks/quality_control/cli/qa_seed_targets.rb +69 -0
  523. data/lib/hecks/quality_control/cli/qa_sweep/all_mode.rb +280 -0
  524. data/lib/hecks/quality_control/cli/qa_sweep/checks.rb +329 -0
  525. data/lib/hecks/quality_control/cli/qa_sweep/dials.rb +92 -0
  526. data/lib/hecks/quality_control/cli/qa_sweep/finding_report.rb +117 -0
  527. data/lib/hecks/quality_control/cli/qa_sweep/parsing.rb +175 -0
  528. data/lib/hecks/quality_control/cli/qa_sweep/release_mode.rb +60 -0
  529. data/lib/hecks/quality_control/cli/qa_sweep.rb +611 -0
  530. data/lib/hecks/quality_control/cli/qa_tick.rb +274 -0
  531. data/lib/hecks/quality_control/quality_control.bluebook +2224 -0
  532. data/lib/hecks/quality_control/quality_control.hecksagon +13 -0
  533. data/lib/hecks/quality_control/quality_control.ports.hecksagon +54 -0
  534. data/lib/hecks/query_ir.rb +346 -0
  535. data/lib/hecks/query_ir_mcp.rb +198 -0
  536. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  537. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  538. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  539. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  540. data/lib/hecks/query_specification/common/options.rb +2 -6
  541. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  542. data/lib/hecks/query_specification/field_path.rb +37 -77
  543. data/lib/hecks/query_specification/hop_path.rb +12 -76
  544. data/lib/hecks/release/gem_pin.rb +2 -26
  545. data/lib/hecks/release/runner/ci_publisher.rb +5 -8
  546. data/lib/hecks/release/runner/clean_tree.rb +42 -0
  547. data/lib/hecks/release/runner/commands.rb +2 -4
  548. data/lib/hecks/release/runner/console.rb +6 -0
  549. data/lib/hecks/release/runner/gem_publisher.rb +15 -9
  550. data/lib/hecks/release/runner/npm_publisher.rb +9 -53
  551. data/lib/hecks/release/runner/preflight.rb +29 -20
  552. data/lib/hecks/release/runner/published.rb +8 -26
  553. data/lib/hecks/release/runner/tagger.rb +31 -23
  554. data/lib/hecks/release/runner.rb +60 -38
  555. data/lib/hecks/rendering.rb +4 -26
  556. data/lib/hecks/router/namespace_installer.rb +15 -39
  557. data/lib/hecks/router.rb +4 -8
  558. data/lib/hecks/runtime/adapter_lookup.rb +124 -0
  559. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  560. data/lib/hecks/runtime/boot_gates.rb +3 -18
  561. data/lib/hecks/runtime/caller.rb +19 -59
  562. data/lib/hecks/runtime/capability_graph.rb +5 -21
  563. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  564. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +27 -160
  565. data/lib/hecks/runtime/command_interpreter.rb +124 -306
  566. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  567. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  568. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  569. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  570. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  571. data/lib/hecks/runtime/dependency_planning.rb +50 -104
  572. data/lib/hecks/runtime/dispatcher.rb +134 -243
  573. data/lib/hecks/runtime/entity_element.rb +40 -462
  574. data/lib/hecks/runtime/entity_interpreter.rb +64 -219
  575. data/lib/hecks/runtime/errors.rb +32 -115
  576. data/lib/hecks/runtime/event.rb +3 -25
  577. data/lib/hecks/runtime/identity.rb +18 -154
  578. data/lib/hecks/runtime/instance.rb +18 -150
  579. data/lib/hecks/runtime/interpreting.rb +14 -70
  580. data/lib/hecks/runtime/invocation.rb +28 -164
  581. data/lib/hecks/runtime/loader.rb +109 -194
  582. data/lib/hecks/runtime/outbox.rb +39 -262
  583. data/lib/hecks/runtime/policy_interpreter.rb +43 -202
  584. data/lib/hecks/runtime/port_operation_interpreter.rb +28 -97
  585. data/lib/hecks/runtime/query_interpreter.rb +122 -187
  586. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  587. data/lib/hecks/runtime/reaction_outcome.rb +89 -0
  588. data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
  589. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  590. data/lib/hecks/runtime/reference_hop.rb +8 -81
  591. data/lib/hecks/runtime/refusal_wording.rb +28 -87
  592. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  593. data/lib/hecks/runtime/registry/verification.rb +213 -227
  594. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  595. data/lib/hecks/runtime/registry.rb +156 -247
  596. data/lib/hecks/runtime/remote_dispatcher.rb +68 -154
  597. data/lib/hecks/runtime/routing.rb +4 -15
  598. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  599. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  600. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  601. data/lib/hecks/runtime/tenant_check.rb +6 -68
  602. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  603. data/lib/hecks/runtime/value/admission.rb +16 -67
  604. data/lib/hecks/runtime/value/coercion.rb +162 -760
  605. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  606. data/lib/hecks/runtime/value/field_checks.rb +172 -0
  607. data/lib/hecks/runtime/value.rb +15 -84
  608. data/lib/hecks/runtime.rb +35 -69
  609. data/lib/hecks/rust_build/conformance.rb +158 -0
  610. data/lib/hecks/rust_build/conformance_fuzz.rb +71 -0
  611. data/lib/hecks/rust_build/coverage.rb +218 -0
  612. data/lib/hecks/rust_build/native_build.rb +124 -0
  613. data/lib/hecks/rust_build/project_rust/root_mod.rb +120 -0
  614. data/lib/hecks/rust_build/project_rust.rb +332 -0
  615. data/lib/hecks/rust_build/wasm.rb +105 -0
  616. data/lib/hecks/rust_build/wasm_browser.rb +113 -0
  617. data/lib/hecks/rust_build.rb +144 -0
  618. data/lib/hecks/storehouse.rb +155 -582
  619. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +10 -34
  620. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  621. data/lib/hecks/three_zero/forms.yml +127 -0
  622. data/lib/hecks/three_zero.rb +12 -0
  623. data/lib/hecks/tools/argument_gate_matrix.rb +316 -0
  624. data/lib/hecks/tools/comment_style.rb +1070 -0
  625. data/lib/hecks/tools/corpus_report.rb +87 -0
  626. data/lib/hecks/tools/deploy_recipe.rb +255 -0
  627. data/lib/hecks/tools/deploy_recipe_lint.rb +282 -0
  628. data/lib/hecks/tools/drop_implicit_append_fields.rb +95 -0
  629. data/lib/hecks/tools/era_projection_backfill.rb +94 -0
  630. data/lib/hecks/tools/era_reattest.rb +146 -0
  631. data/lib/hecks/tools/evolve_run.rb +189 -0
  632. data/lib/hecks/tools/fuzz_sweep.rb +373 -0
  633. data/lib/hecks/tools/heki_compaction.rb +100 -0
  634. data/lib/hecks/tools/hoist_local_givens.rb +246 -0
  635. data/lib/hecks/tools/journal_compaction.rb +89 -0
  636. data/lib/hecks/tools/oidc_manifests.rb +70 -0
  637. data/lib/hecks/tools/query_ir_run.rb +81 -0
  638. data/lib/hecks/tools/regeneration_run.rb +166 -0
  639. data/lib/hecks/tools/rust_comment_style.rb +642 -0
  640. data/lib/hecks/tools/sequence_script.rb +62 -0
  641. data/lib/hecks/tools/tail_merge.rb +117 -0
  642. data/lib/hecks/tools/tenant_provisioning.rb +142 -0
  643. data/lib/hecks/tools/translation_audit.rb +208 -0
  644. data/lib/hecks/tools/translation_scaffold.rb +131 -0
  645. data/lib/hecks/tools.rb +86 -0
  646. data/lib/hecks/vendoring/git_environment.rb +2 -8
  647. data/lib/hecks/vendoring/git_source.rb +4 -10
  648. data/lib/hecks/vendoring.rb +7 -46
  649. data/lib/hecks/version.rb +3 -14
  650. data/lib/hecks.rb +52 -90
  651. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  652. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  653. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  654. data/qa/settings.yml +66 -0
  655. data/rust/.cargo/config.toml +6 -0
  656. data/rust/.gitignore +2 -0
  657. data/rust/Cargo.lock +54 -0
  658. data/rust/Cargo.toml +61 -0
  659. data/rust/build/.cargo/config.toml +3 -0
  660. data/rust/build/.gitignore +1 -0
  661. data/rust/build/Cargo.lock +7 -0
  662. data/rust/build/Cargo.toml +19 -0
  663. data/rust/build/src/build_artifact.rs +47 -0
  664. data/rust/build/src/cargo_sync.rs +248 -0
  665. data/rust/build/src/json.rs +421 -0
  666. data/rust/build/src/lineage_pass.rs +285 -0
  667. data/rust/build/src/main.rs +51 -0
  668. data/rust/build/src/optional_pass.rs +150 -0
  669. data/rust/build/src/pipeline.rs +264 -0
  670. data/rust/build/src/reserved_names.rs +76 -0
  671. data/rust/build/src/resolve.rs +124 -0
  672. data/rust/build/src/root.rs +25 -0
  673. data/rust/build/src/sidecars.rs +73 -0
  674. data/rust/build/src/subprocess.rs +51 -0
  675. data/rust/build/src/tmp.rs +31 -0
  676. data/rust/codegen/.cargo/config.toml +3 -0
  677. data/rust/codegen/.gitignore +1 -0
  678. data/rust/codegen/Cargo.lock +7 -0
  679. data/rust/codegen/Cargo.toml +20 -0
  680. data/rust/codegen/src/attr.rs +32 -0
  681. data/rust/codegen/src/bridging.rs +481 -0
  682. data/rust/codegen/src/commands.rs +1226 -0
  683. data/rust/codegen/src/constraints.rs +109 -0
  684. data/rust/codegen/src/dependency_planning.rs +209 -0
  685. data/rust/codegen/src/domain_generator.rs +1288 -0
  686. data/rust/codegen/src/exemplar.rs +230 -0
  687. data/rust/codegen/src/expr_emitter.rs +87 -0
  688. data/rust/codegen/src/fielded.rs +192 -0
  689. data/rust/codegen/src/hecks_naming.rs +33 -0
  690. data/rust/codegen/src/json.rs +335 -0
  691. data/rust/codegen/src/json_codec.rs +697 -0
  692. data/rust/codegen/src/literal.rs +207 -0
  693. data/rust/codegen/src/main.rs +290 -0
  694. data/rust/codegen/src/manifest.rs +227 -0
  695. data/rust/codegen/src/mutations.rs +784 -0
  696. data/rust/codegen/src/naming.rs +286 -0
  697. data/rust/codegen/src/ports.rs +208 -0
  698. data/rust/codegen/src/prelude.rs +116 -0
  699. data/rust/codegen/src/queries.rs +786 -0
  700. data/rust/codegen/src/reactions.rs +532 -0
  701. data/rust/codegen/src/read_models.rs +697 -0
  702. data/rust/codegen/src/reference_specs.rs +40 -0
  703. data/rust/codegen/src/registry.rs +966 -0
  704. data/rust/codegen/src/reserved_names.rs +76 -0
  705. data/rust/codegen/src/shared.rs +93 -0
  706. data/rust/codegen/src/skip_reason.rs +25 -0
  707. data/rust/codegen/src/types.rs +362 -0
  708. data/rust/host/.cargo/config.toml +3 -0
  709. data/rust/host/.gitignore +1 -0
  710. data/rust/host/Cargo.lock +4297 -0
  711. data/rust/host/Cargo.toml +61 -0
  712. data/rust/host/HECKS_RELEASE +1 -0
  713. data/rust/host/rds-ca-bundle.pem +2736 -0
  714. data/rust/host/src/api.rs +1596 -0
  715. data/rust/host/src/approval.rs +652 -0
  716. data/rust/host/src/auth.rs +1287 -0
  717. data/rust/host/src/bin/expr_harness.rs +46 -0
  718. data/rust/host/src/bin/lineage_harness.rs +119 -0
  719. data/rust/host/src/bin/mint_harness.rs +135 -0
  720. data/rust/host/src/checkout.rs +265 -0
  721. data/rust/host/src/dispatch.rs +1443 -0
  722. data/rust/host/src/expr_json.rs +1117 -0
  723. data/rust/host/src/field_hints.rs +52 -0
  724. data/rust/host/src/ir.rs +733 -0
  725. data/rust/host/src/journal.rs +874 -0
  726. data/rust/host/src/lambda_client.rs +378 -0
  727. data/rust/host/src/log.rs +147 -0
  728. data/rust/host/src/main.rs +474 -0
  729. data/rust/host/src/mint.rs +1865 -0
  730. data/rust/host/src/payments/keystore.rs +330 -0
  731. data/rust/host/src/payments/tests.rs +1400 -0
  732. data/rust/host/src/payments.rs +767 -0
  733. data/rust/host/src/presentation.rs +698 -0
  734. data/rust/host/src/presentation_write.rs +1431 -0
  735. data/rust/host/src/query_step.rs +149 -0
  736. data/rust/host/src/rate_limit.rs +904 -0
  737. data/rust/host/src/reference_transform.rs +241 -0
  738. data/rust/host/src/reference_validate.rs +338 -0
  739. data/rust/host/src/resend.rs +296 -0
  740. data/rust/host/src/secrets.rs +106 -0
  741. data/rust/host/src/server.rs +663 -0
  742. data/rust/host/src/storage_shape.rs +175 -0
  743. data/rust/host/src/test_pg.rs +40 -0
  744. data/rust/host/src/ui_schema.rs +1351 -0
  745. data/rust/host/src/wasm_runner.rs +191 -0
  746. data/rust/host/src/web/newsletter/cooldown.rs +126 -0
  747. data/rust/host/src/web/newsletter/tests.rs +104 -0
  748. data/rust/host/src/web/newsletter.rs +310 -0
  749. data/rust/host/src/web/newsletter_send.rs +357 -0
  750. data/rust/host/src/web/registrations.rs +1505 -0
  751. data/rust/host/src/web.rs +2937 -0
  752. data/rust/lsp/.gitignore +1 -0
  753. data/rust/lsp/Cargo.lock +7 -0
  754. data/rust/lsp/Cargo.toml +16 -0
  755. data/rust/lsp/README.md +133 -0
  756. data/rust/lsp/src/diagnostics.rs +165 -0
  757. data/rust/lsp/src/json.rs +385 -0
  758. data/rust/lsp/src/main.rs +399 -0
  759. data/rust/lsp/src/outline.rs +177 -0
  760. data/rust/lsp/src/rpc.rs +67 -0
  761. data/rust/parser/.cargo/config.toml +5 -0
  762. data/rust/parser/.gitignore +1 -0
  763. data/rust/parser/Cargo.lock +7 -0
  764. data/rust/parser/Cargo.toml +21 -0
  765. data/rust/parser/src/build/closed_sets.rs +27 -0
  766. data/rust/parser/src/build/identity.rs +276 -0
  767. data/rust/parser/src/build/mod.rs +12 -0
  768. data/rust/parser/src/build/naming.rs +141 -0
  769. data/rust/parser/src/build/pattern_subset.rs +161 -0
  770. data/rust/parser/src/build/query_derive.rs +72 -0
  771. data/rust/parser/src/build/query_inference.rs +269 -0
  772. data/rust/parser/src/build/query_options.rs +100 -0
  773. data/rust/parser/src/build/read_model.rs +94 -0
  774. data/rust/parser/src/build/references.rs +32 -0
  775. data/rust/parser/src/canonical.rs +114 -0
  776. data/rust/parser/src/diag.rs +55 -0
  777. data/rust/parser/src/emit.rs +953 -0
  778. data/rust/parser/src/expr/ast_json.rs +147 -0
  779. data/rust/parser/src/expr/evaluator.rs +81 -0
  780. data/rust/parser/src/expr/mod.rs +84 -0
  781. data/rust/parser/src/expr/resolver.rs +497 -0
  782. data/rust/parser/src/ir.rs +387 -0
  783. data/rust/parser/src/keywords.rs +585 -0
  784. data/rust/parser/src/lex.rs +662 -0
  785. data/rust/parser/src/main.rs +252 -0
  786. data/rust/parser/src/parse/aggregate.rs +612 -0
  787. data/rust/parser/src/parse/chapter.rs +517 -0
  788. data/rust/parser/src/parse/command.rs +637 -0
  789. data/rust/parser/src/parse/domain_port.rs +127 -0
  790. data/rust/parser/src/parse/entity.rs +527 -0
  791. data/rust/parser/src/parse/file.rs +67 -0
  792. data/rust/parser/src/parse/hecksagon.rs +231 -0
  793. data/rust/parser/src/parse/lifecycle.rs +162 -0
  794. data/rust/parser/src/parse/mod.rs +1262 -0
  795. data/rust/parser/src/parse/policy.rs +87 -0
  796. data/rust/parser/src/parse/process_manager.rs +305 -0
  797. data/rust/parser/src/parse/query.rs +100 -0
  798. data/rust/parser/src/parse/read_model.rs +214 -0
  799. data/rust/parser/src/parse/value_object.rs +250 -0
  800. data/rust/parser/src/ruby_value.rs +422 -0
  801. data/rust/project/bridging.rb +257 -0
  802. data/rust/project/commands.rb +877 -0
  803. data/rust/project/constraints.rb +86 -0
  804. data/rust/project/dependency_planning.rb +178 -0
  805. data/rust/project/domain_generator.rb +980 -0
  806. data/rust/project/exemplar.rb +148 -0
  807. data/rust/project/expr_emitter.rb +72 -0
  808. data/rust/project/fielded.rb +141 -0
  809. data/rust/project/json_codec.rb +641 -0
  810. data/rust/project/mutations.rb +721 -0
  811. data/rust/project/naming.rb +205 -0
  812. data/rust/project/ports.rb +65 -0
  813. data/rust/project/queries.rb +493 -0
  814. data/rust/project/reactions.rb +317 -0
  815. data/rust/project/read_models.rb +690 -0
  816. data/rust/project/reference_specs.rb +27 -0
  817. data/rust/project/registry.rb +396 -0
  818. data/rust/project/skip_reason.rb +29 -0
  819. data/rust/project/types.rb +225 -0
  820. data/rust/project/write_if_changed.rb +83 -0
  821. data/rust/project.rb +30 -0
  822. data/rust/project_rust_pipeline.rb +383 -0
  823. data/rust/src/exemplar/commands.rs +279 -0
  824. data/rust/src/exemplar/constraints.rs +18 -0
  825. data/rust/src/exemplar/fielded.rs +280 -0
  826. data/rust/src/exemplar/json.rs +277 -0
  827. data/rust/src/exemplar/mod.rs +17 -0
  828. data/rust/src/exemplar/mutations.rs +80 -0
  829. data/rust/src/exemplar/queries.rs +33 -0
  830. data/rust/src/exemplar/reactions.rs +88 -0
  831. data/rust/src/exemplar/read_models.rs +48 -0
  832. data/rust/src/exemplar/registry.rs +166 -0
  833. data/rust/src/exemplar/types.rs +44 -0
  834. data/rust/src/kernel/attribute_shapes/composite.rs +88 -0
  835. data/rust/src/kernel/attribute_shapes/list.rs +18 -0
  836. data/rust/src/kernel/attribute_shapes/mod.rs +44 -0
  837. data/rust/src/kernel/attribute_shapes/optional.rs +9 -0
  838. data/rust/src/kernel/attribute_shapes/scalar.rs +39 -0
  839. data/rust/src/kernel/cli.rs +585 -0
  840. data/rust/src/kernel/dispatch.rs +1090 -0
  841. data/rust/src/kernel/expr.rs +458 -0
  842. data/rust/src/kernel/expression_operators/arithmetic.rs +128 -0
  843. data/rust/src/kernel/expression_operators/comparison.rs +48 -0
  844. data/rust/src/kernel/expression_operators/enumeration.rs +232 -0
  845. data/rust/src/kernel/expression_operators/logical.rs +13 -0
  846. data/rust/src/kernel/expression_operators/membership.rs +18 -0
  847. data/rust/src/kernel/expression_operators/mod.rs +68 -0
  848. data/rust/src/kernel/expression_operators/pattern_match.rs +73 -0
  849. data/rust/src/kernel/expression_operators/positional.rs +126 -0
  850. data/rust/src/kernel/expression_operators/presence.rs +101 -0
  851. data/rust/src/kernel/expression_operators/sign_test.rs +16 -0
  852. data/rust/src/kernel/expression_operators/sized.rs +35 -0
  853. data/rust/src/kernel/expression_operators/text.rs +79 -0
  854. data/rust/src/kernel/expression_operators/to_string.rs +18 -0
  855. data/rust/src/kernel/json.rs +779 -0
  856. data/rust/src/kernel/mod.rs +133 -0
  857. data/rust/src/kernel/named_query.rs +219 -0
  858. data/rust/src/kernel/orchestrate.rs +1810 -0
  859. data/rust/src/kernel/pattern.rs +307 -0
  860. data/rust/src/kernel/query_comparators.rs +206 -0
  861. data/rust/src/kernel/query_ordering.rs +103 -0
  862. data/rust/src/kernel/read_model.rs +914 -0
  863. data/rust/src/kernel/reference_lookup.rs +149 -0
  864. data/rust/src/kernel/repository.rs +468 -0
  865. data/rust/src/kernel/routing.rs +612 -0
  866. data/rust/src/kernel/vocab/aggregate_dispatch_order.rs +118 -0
  867. data/rust/src/kernel/vocab/entity_dispatch_order.rs +114 -0
  868. data/rust/src/kernel/vocab/field_hint.rs +70 -0
  869. data/rust/src/kernel/vocab/mod.rs +20 -0
  870. data/rust/src/kernel/vocab/query_comparator.rs +65 -0
  871. data/rust/src/kernel/vocab/refusal_template.rs +1592 -0
  872. data/rust/src/lib.rs +8 -0
  873. data/rust/src/main.rs +16 -0
  874. data/rust/web/.gitignore +1 -0
  875. data/rust/web/Cargo.lock +119 -0
  876. data/rust/web/Cargo.toml +18 -0
  877. data/rust/web/src/lib.rs +8 -0
  878. metadata +478 -12
  879. data/lib/hecks/facade/cli_door.rb +0 -178
  880. data/lib/hecks/facade/cli_runner.rb +0 -271
  881. data/lib/hecks/facade/handle.rb +0 -293
  882. data/lib/hecks/facade/json_door.rb +0 -247
  883. data/lib/hecks/facade/surface/aggregate_door.rb +0 -222
  884. data/lib/hecks/facade/surface/chapter.rb +0 -116
  885. data/lib/hecks/facade/surface.rb +0 -61
  886. data/lib/hecks/mcp_door_scope.rb +0 -176
@@ -1,59 +1,20 @@
1
1
  require "json"
2
2
  require_relative "../../hecks"
3
- require_relative "mcp"
3
+ require_relative "../cli/mcp"
4
4
 
5
5
  module Hecks
6
- module CLI
7
- # The MCP door onto the storehouse bus: one MCP server for every booted domain,
8
- # not one per command, hand-rolled JSON-RPC over stdio (newline-delimited JSON,
9
- # flushed after every write, no gem dependency).
6
+ module Doors
7
+ # The MCP door onto the storehouse bus: hand-rolled JSON-RPC over stdio, one
8
+ # server per booted domain. All logic and the JSON shape answered with live in
9
+ # `Storehouse`; this is plumbing only. A `role:`/`actor_id:` a caller sends is
10
+ # asserted, not verified, unless Governance is attached.
10
11
  #
11
- # ## Plumbing only
12
- #
13
- # All the logic and the JSON shape it answers with live in `Storehouse`, the bus
14
- # itself, transport-blind. A door of another shape (a plain CLI, an HTTP door)
15
- # would sit beside this one, calling `Storehouse` the same way and sharing its
16
- # audit log and caller-identity handling.
17
- #
18
- # ## Identity is asserted, not verified
19
- #
20
- # `dispatch` and `query` take `role:` and `actor_id:`, bound for the call through
21
- # `Hecks.as_caller`, so a role-gated command is checked against them rather than
22
- # merely documented by `describe`; `dispatch` refuses a role-declaring command
23
- # called without one. Nothing here verifies the claim beyond the string (or, with
24
- # Governance attached, a `Governance::RoleAssignment` lookup). The readers take
25
- # no role, and `query` gates on none.
26
- #
27
- # ## Stdio only, enforced
28
- #
29
- # The door has no authentication. `Mcp.call` runs
30
- # `McpStdioGuard.enforce_stdio!` before this file loads, and `serve` prints the
31
- # warning to stderr, never stdout, which carries the protocol. `domain:` is
32
- # confined to `Storehouse::BOOT_ROOT` (`confine!`), but a domain within that
33
- # root still boots real Ruby, so this is a code execution surface for anyone who
34
- # can write to stdin. A network transport needs authentication first; see
35
- # `docs/decisions/0062-mcp-servers-need-real-authentication-before-any-network-transport.md`.
36
- #
37
- # ## Reader mode
38
- #
39
- # Whoever spawns the door can narrow it with `HECKS_DOOR_TOOLS=readers` and
40
- # `HECKS_DOOR_DOMAINS=<dir>[:<dir>...]` (`Hecks::McpDoorScope`, ADR 0072 decision 2).
41
- # A reader door serves only `McpDoorScope::READER_TOOLS` (`query`, `events`,
42
- # `state`, `catalog`, `describe`, `validate`, `domains`, `history`, `follow`), lists
43
- # only those in `tools/list`, and refuses `dispatch` (so `dry_run` and `steps` too),
44
- # `behaviors` and any other name with an answer that names the mode. Its `domain:`
45
- # must resolve to one of the named directories, checked before anything boots, so no
46
- # other domain's Ruby is loaded. The door keeps no domain loaded between calls, so
47
- # the named list is the whole allowed set. This limits what one spawned agent can
48
- # reach; it identifies no one and is not authentication. The names sit outside
49
- # `HECKS_MCP_*` because the stdio guard refuses every name in that prefix but the
50
- # transport, and that refusal belongs to ADR 0062. With neither variable set, the
51
- # door serves every tool as described above.
52
- #
53
- # ## One boot per call
54
- #
55
- # `Hecks.boot(domain, install_facade: false)` is cheap, and it lets one server
56
- # answer calls against two domains back to back with no shared, staling state.
12
+ # There is no authentication: `domain:` boots real Ruby confined to
13
+ # `Storehouse::BOOT_ROOT`, so this is a code execution surface for anyone who
14
+ # can write to stdin (ADR 0062). Spawning with `HECKS_DOOR_TOOLS=readers` and
15
+ # `HECKS_DOOR_DOMAINS=<dir>[:<dir>...]` narrows a door to read-only tools and
16
+ # named domains (`McpDoorScope`); this limits what one agent can reach and is
17
+ # not itself authentication.
57
18
  module McpDoor
58
19
  PROTOCOL_VERSION = "2024-11-05".freeze
59
20
 
@@ -271,29 +232,19 @@ module Hecks
271
232
 
272
233
  module_function
273
234
 
274
- # The scope this door was spawned with: every tool and any domain, or a reader
275
- # door narrowed by `HECKS_DOOR_TOOLS`/`HECKS_DOOR_DOMAINS`. Read once, on first use,
276
- # so a bad setting refuses to start the door before anything is written to stdout.
277
- #
278
- # @return [McpDoorScope]
235
+ # Read once, so a bad setting refuses to start the door before anything is
236
+ # written to stdout.
279
237
  def scope
280
- @scope ||= McpDoorScope.start!(server: Mcp::SERVER)
238
+ @scope ||= McpDoorScope.start!(server: CLI::Mcp::SERVER)
281
239
  end
282
240
 
283
- # The notes the stdio warning carries: the standing ones, then what this door's
284
- # scope says about `domain:`.
285
- #
286
- # @return [Array<String>]
241
+ # The standing notes, then what this door's scope says about `domain:`.
287
242
  def warning_notes
288
243
  NOTES[0, 2] + (scope.restricted? ? scope.notes : [NOTES[2]])
289
244
  end
290
245
 
291
- # Prints the stdio warning to stderr, then answers one JSON-RPC request per
292
- # line of `$stdin` until it closes.
293
- #
294
- # @return [void]
295
246
  def serve
296
- McpStdioGuard.warn!(server: Mcp::SERVER, notes: warning_notes)
247
+ McpStdioGuard.warn!(server: CLI::Mcp::SERVER, notes: warning_notes)
297
248
  $stdout.sync = true
298
249
 
299
250
  $stdin.each_line do |line|
@@ -315,29 +266,14 @@ module Hecks
315
266
  end
316
267
  end
317
268
 
318
- # Boots one domain for a single call, confined to `Storehouse::BOOT_ROOT`.
319
- #
320
- # @param domain [String] the domain directory, e.g. `"examples/banking"`
321
- # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted domain
322
- # @raise [Runtime::TypeMismatch] if `domain` resolves outside `Storehouse::BOOT_ROOT`, or,
323
- # on a reader door, outside `HECKS_DOOR_DOMAINS`
324
- # @raise [Runtime::WiringError] if the domain fails to boot
269
+ # `domain:` is confined to `Storehouse::BOOT_ROOT`, and further to a reader
270
+ # door's `HECKS_DOOR_DOMAINS`, before anything boots.
325
271
  def boot(domain)
326
- Hecks.boot(Storehouse.confine!(scope.admit_domain!(domain), "domain"), install_facade: false)
272
+ Hecks.boot(Storehouse.confine!(scope.admit_domain!(domain), "domain"), install_doors: false)
327
273
  end
328
274
 
329
- # Runs one registered MCP tool by delegating to the matching `Storehouse` call.
330
- #
331
- # A closed-set dispatch table, one `when` per tool, so the size is the tool
332
- # count and the shared `rescue` catches every branch's escape once.
333
- #
334
- # @param name [String] the tool name, one of `TOOLS`'s own `:name` values
335
- # @param args [Hash{String => Object}] the tool's JSON arguments, shaped per that
336
- # tool's `inputSchema`
337
- # @return [Hash{Symbol => Object}] the delegated `Storehouse` result on a known
338
- # tool name; `{ok: false, error: String}` for an unknown tool name or any
339
- # `StandardError` this door did not anticipate (a domain refusal is already
340
- # `{ok: false, ...}` from inside `Storehouse` itself)
275
+ # One `when` per tool, so the shared `rescue` catches every branch's escape
276
+ # once; a domain refusal is already `{ok: false, ...}` from `Storehouse`.
341
277
  def call_tool(name, args) # rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity
342
278
  case name
343
279
  when "dispatch"
@@ -378,60 +314,29 @@ module Hecks
378
314
  { ok: false, error: "no such tool: #{name.inspect} — known: #{TOOLS.map { |t| t[:name] }.join(', ')}" }
379
315
  end
380
316
  rescue StandardError => e
381
- # **A defect, not a refusal** — every domain refusal is already answered as
382
- # `{ok: false, error: "..."}` inside `Storehouse`. Reaching here means a bad
383
- # domain path or an argument shape `Facade::JsonDoor` could not symbolize,
384
- # still answered as structured content rather than an MCP-level `isError`,
385
- # so a calling agent reads one shape for every outcome.
317
+ # A defect, not a refusal: reaching here means a bad domain path or an
318
+ # argument shape `Doors::JsonDoor` could not symbolize.
386
319
  { ok: false, error: "#{e.class}: #{e.message}" }
387
320
  end
388
321
 
389
- # Runs one MCP tool call if this door's mode serves it, and refuses it otherwise.
390
- #
391
- # @param name [String] the tool name from the `tools/call` request
392
- # @param args [Hash{String => Object}] the tool's JSON arguments
393
- # @return [Hash{Symbol => Object}] the `call_tool` result, or `scope.refusal(name)`
394
- # when a reader door does not serve `name`
395
322
  def answer_tool(name, args)
396
323
  return scope.refusal(name) unless scope.permits_tool?(name)
397
324
 
398
325
  call_tool(name, args)
399
326
  end
400
327
 
401
- # Wraps a `call_tool` payload in the MCP `tools/call` result shape.
402
- #
403
- # @param payload [Hash{Symbol => Object}] a `call_tool` result
404
- # @return [Hash{Symbol => Object}] `{content: [{type: "text", text: ...}], isError: Boolean}`,
405
- # pretty-printing `payload` as the text and setting `isError` from `payload[:ok]`
406
328
  def tool_result(payload)
407
329
  { content: [{ type: "text", text: JSON.pretty_generate(payload) }], isError: payload[:ok] == false }
408
330
  end
409
331
 
410
- # Writes one JSON-RPC success response line to stdout.
411
- #
412
- # @param id [String, Integer, nil] the request's own `id`, echoed back
413
- # @param result [Object] the JSON-serializable result payload
414
- # @return [void]
415
332
  def send_response(id, result)
416
333
  puts JSON.generate({ jsonrpc: "2.0", id: id, result: result })
417
334
  end
418
335
 
419
- # Writes one JSON-RPC error response line to stdout.
420
- #
421
- # @param id [String, Integer, nil] the request's own `id`, echoed back; nil when
422
- # the request itself could not be parsed
423
- # @param code [Integer] the JSON-RPC error code
424
- # @param message [String] the error message
425
- # @return [void]
426
336
  def send_error(id, code, message)
427
337
  puts JSON.generate({ jsonrpc: "2.0", id: id, error: { code: code, message: message } })
428
338
  end
429
339
 
430
- # Dispatches one parsed JSON-RPC request to its method and writes the response.
431
- #
432
- # @param request [Hash{String => Object}] one parsed JSON-RPC request, with
433
- # `"id"`, `"method"`, and optional `"params"`
434
- # @return [void]
435
340
  def handle(request)
436
341
  id = request["id"]
437
342
  method = request["method"]
@@ -442,7 +347,7 @@ module Hecks
442
347
  send_response(id, {
443
348
  protocolVersion: PROTOCOL_VERSION,
444
349
  capabilities: { tools: {} },
445
- serverInfo: { name: Mcp::SERVER, version: "1.1.0" }
350
+ serverInfo: { name: CLI::Mcp::SERVER, version: "1.1.0" }
446
351
  })
447
352
  when "notifications/initialized"
448
353
  nil # a notification — no id, no response
@@ -0,0 +1,97 @@
1
+ require_relative "../runtime/errors"
2
+
3
+ module Hecks
4
+ module Doors
5
+ # What a spawned hecks mcp may do: every tool by default, or only
6
+ # reader tools against named domains in reader mode — reach, not identity (ADR 0072).
7
+ class McpDoorScope
8
+ ENV_PREFIX = "HECKS_DOOR_".freeze
9
+ TOOLS_VARIABLE = "HECKS_DOOR_TOOLS".freeze
10
+ DOMAINS_VARIABLE = "HECKS_DOOR_DOMAINS".freeze
11
+ READERS = "readers".freeze
12
+ EXIT_STATUS = 2
13
+
14
+ # The tools a reader door serves — each reads a domain or the door's own
15
+ # audit log and writes no domain state. `validate` still boots its
16
+ # domain, so it stays bound to the allowed set like every other tool.
17
+ READER_TOOLS = %w[query events state catalog describe validate domains history follow].freeze
18
+
19
+ # Unrestricted when no HECKS_DOOR_* variable is set.
20
+ def self.from_env(env = ENV)
21
+ problems = setting_problems(env)
22
+ raise ArgumentError, problems.join("\n") unless problems.empty?
23
+ return new(allowed_domains: nil) unless env[TOOLS_VARIABLE]
24
+
25
+ new(allowed_domains: env[DOMAINS_VARIABLE].split(File::PATH_SEPARATOR).reject(&:empty?))
26
+ end
27
+
28
+ # Refuses to stderr, not stdout, which carries the MCP protocol.
29
+ def self.start!(server:, env: ENV, stderr: $stderr)
30
+ from_env(env)
31
+ rescue ArgumentError, Runtime::TypeMismatch => e
32
+ e.message.each_line { |line| stderr.puts("#{server}: refusing to start: #{line.chomp}") }
33
+ exit(EXIT_STATUS)
34
+ end
35
+
36
+ def self.setting_problems(env)
37
+ unknown = env.keys.select { |name| name.start_with?(ENV_PREFIX) } - [TOOLS_VARIABLE, DOMAINS_VARIABLE]
38
+ problems = unknown.map do |name|
39
+ "environment #{name} is not accepted; the door takes only #{TOOLS_VARIABLE} and #{DOMAINS_VARIABLE}"
40
+ end
41
+ problems + mode_problems(env[TOOLS_VARIABLE], env[DOMAINS_VARIABLE])
42
+ end
43
+
44
+ def self.mode_problems(tools, domains)
45
+ if tools.nil?
46
+ domains.nil? ? [] : ["#{DOMAINS_VARIABLE} is set without #{TOOLS_VARIABLE}=#{READERS}; it only narrows a reader door"]
47
+ elsif tools != READERS
48
+ ["#{TOOLS_VARIABLE}=#{tools.inspect} is not accepted; the only value is #{READERS.inspect}"]
49
+ elsif domains.to_s.split(File::PATH_SEPARATOR).none? { |path| !path.empty? }
50
+ ["#{TOOLS_VARIABLE}=#{READERS} needs #{DOMAINS_VARIABLE}, the domains this door may read"]
51
+ else
52
+ []
53
+ end
54
+ end
55
+
56
+ # The named domains, resolved against Storehouse::BOOT_ROOT; nil when unrestricted.
57
+ attr_reader :allowed_domains
58
+
59
+ def initialize(allowed_domains:)
60
+ @allowed_domains = allowed_domains&.map { |path| Storehouse.confine!(path, DOMAINS_VARIABLE) }.freeze
61
+ end
62
+
63
+ def restricted?
64
+ !@allowed_domains.nil?
65
+ end
66
+
67
+ def permits_tool?(name)
68
+ !restricted? || READER_TOOLS.include?(name)
69
+ end
70
+
71
+ def refusal(name)
72
+ { ok: false,
73
+ error: "#{name.inspect} is refused: this door runs in reader mode (#{TOOLS_VARIABLE}=#{READERS}), " \
74
+ "which serves only #{READER_TOOLS.join(', ')}" }
75
+ end
76
+
77
+ # Checked before anything boots, so a path outside the allowed set never reaches Kernel.load.
78
+ def admit_domain!(domain)
79
+ return domain unless restricted?
80
+ return domain if @allowed_domains.include?(Storehouse.confine!(domain, "domain"))
81
+
82
+ raise Runtime::TypeMismatch,
83
+ "domain: #{domain.inspect} is refused: this door runs in reader mode (#{TOOLS_VARIABLE}=#{READERS}) " \
84
+ "and reads only #{DOMAINS_VARIABLE}: #{@allowed_domains.join(', ')}"
85
+ end
86
+
87
+ def notes
88
+ return [] unless restricted?
89
+
90
+ ["Reader mode (#{TOOLS_VARIABLE}=#{READERS}): serves #{READER_TOOLS.join(', ')}; " \
91
+ "refuses dispatch (with dry_run and steps), behaviors and every other tool.",
92
+ "domain: boots only #{DOMAINS_VARIABLE}: #{@allowed_domains.join(', ')}.",
93
+ "Reader mode limits reach and identifies no one; it is not authentication."]
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,162 @@
1
+ require_relative "../../bluebook/dsl/hecksagon_builder"
2
+ require_relative "../../bluebook/dsl/world_builder"
3
+ require_relative "../../bluebook/dsl/domain_port_builder"
4
+ require_relative "../../bluebook/dsl/const_shim"
5
+ require_relative "../../bluebook/dsl/binding_proxy"
6
+ require_relative "../../bluebook/hexagon"
7
+ require_relative "../handle"
8
+ require_relative "../../naming"
9
+
10
+ module Hecks
11
+ module Doors
12
+ module RubyDoor
13
+ # One aggregate's door: creating verbs and queries as module methods, CRUD
14
+ # delegation, and the `.hecksagon` binding/port hooks it lands on.
15
+ module AggregateDoor
16
+ # Builds one aggregate's door module: creating-command methods, query methods,
17
+ # find/all/count/events, project/docs/narrate, and the port/binding hooks.
18
+ #
19
+ # Kept as one method: `:port`/`:method_missing`/`:const_missing` below
20
+ # cross-reference each other and would lose that thread if split up.
21
+ # rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
22
+ def aggregate_module(dispatcher, domain, aggregate)
23
+ fqn = "#{domain}::#{aggregate.hecks_name}"
24
+ door = Module.new
25
+
26
+ aggregate.attributes.each do |attribute|
27
+ next unless RESERVED.include?(attribute.name.to_sym)
28
+
29
+ warn "[hecks] #{aggregate.hecks_name}##{attribute.name} shadows a built-in — no reader defined"
30
+ end
31
+
32
+ # `!` marks a creating command (Ruby's mutate-and-may-refuse convention).
33
+ # Without it, a query sharing the same business name (e.g. Account's
34
+ # "Open") would collide with the creating command's own bare name.
35
+ aggregate.commands.select(&:creates?).each do |command|
36
+ door.define_singleton_method("#{Naming.snake(command.hecks_name)}!") do |**args|
37
+ Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate,
38
+ instance: dispatcher.dispatch("#{fqn}.#{command.hecks_name}", with: args).instance)
39
+ end
40
+ end
41
+
42
+ # A query is a bare module method (no `!`): it just reads and returns
43
+ # the same raw row array `dispatcher.query` itself answers.
44
+ aggregate.queries.each do |query|
45
+ door.define_singleton_method(Naming.snake(query.hecks_name)) do |**args|
46
+ dispatcher.query("#{fqn}.#{query.hecks_name}", **args)
47
+ end
48
+ end
49
+
50
+ door.define_singleton_method(:fqn) { fqn }
51
+ door.define_singleton_method(:ir) { aggregate }
52
+
53
+ # Every construct emits its own IR, so an aggregate is a legitimate
54
+ # `project` target too. A chapter-scoped target refuses here via
55
+ # `Projector.admits!` rather than answering a confidently empty result.
56
+ door.define_singleton_method(:project) do |target, out: nil, **options|
57
+ key = Projector.key_for(target)
58
+ artifact = Projector.call(key, bluebook: aggregate, options: options)
59
+ return artifact unless out
60
+
61
+ Projector.write(artifact, out, as: Projector.emits_for(key))
62
+ end
63
+ door.define_singleton_method(:repository) { dispatcher.registry.repository(domain, aggregate) }
64
+ door.define_singleton_method(:commands) do
65
+ aggregate.commands.map { |c| "#{Naming.snake(c.hecks_name)}!" }.sort
66
+ end
67
+ door.define_singleton_method(:queries) { aggregate.queries.map { |q| Naming.snake(q.hecks_name) }.sort }
68
+ # This chapter's own `:docs` projection, narrowed to this aggregate.
69
+ door.define_singleton_method(:docs) do |**options|
70
+ Projector.call(:docs, bluebook: dispatcher.registry.bluebook(domain),
71
+ options: options.merge(aggregate: aggregate.hecks_name))
72
+ end
73
+ # Same narrowing as `:docs`, aimed at `:narrate`.
74
+ door.define_singleton_method(:narrate) do |**options|
75
+ Projector.call(:narrate, bluebook: dispatcher.registry.bluebook(domain),
76
+ options: options.merge(aggregate: aggregate.hecks_name))
77
+ end
78
+ door.define_singleton_method(:count) { dispatcher.registry.repository(domain, aggregate).count }
79
+ door.define_singleton_method(:events) { dispatcher.events.select { |event| event.aggregate == fqn } }
80
+
81
+ door.define_singleton_method(:find) do |id|
82
+ found = dispatcher.registry.repository(domain, aggregate).find(id)
83
+ found && Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate, instance: found)
84
+ end
85
+
86
+ door.define_singleton_method(:all) do |**opts|
87
+ dispatcher.registry.repository(domain, aggregate).all(**opts).map do |instance|
88
+ Handle.new(dispatcher: dispatcher, domain: domain, aggregate: aggregate, instance: instance)
89
+ end
90
+ end
91
+
92
+ # Re-resolves via `Hecks.current_registry` rather than the closed-over
93
+ # `aggregate`: this door can be stale from an earlier boot, and its own
94
+ # `aggregate` would silently port a discarded one instead of the live one.
95
+ door.define_singleton_method(:port) do |name, &block|
96
+ current = Hecks.current_registry&.bluebook(domain)&.aggregate(aggregate.hecks_name) or
97
+ raise Bluebook::DSL::Malformed, "#{fqn}.port(#{name.inspect}) called outside a boot"
98
+
99
+ built = Bluebook::DSL::ConstShim.with(->(const) { const }) do
100
+ Bluebook::DSL::DomainPortBuilder.build(name, owner: current.hecks_name, &block)
101
+ end
102
+
103
+ # A `verb`-shaped port is a plain `Port`, the same struct `Hecks.port` registers —
104
+ # it belongs to no aggregate IR the way an operations-shaped `DomainPort` does, so
105
+ # it takes the registry's `add_port` directly. Mirrors `DSL::BindingProxy#port`,
106
+ # which handles the identical shape on a domain's first in-process boot (before
107
+ # this facade constant exists); this method is what a repeat boot reaches instead.
108
+ if built.is_a?(Bluebook::Port)
109
+ Hecks.current_registry.add_port(built)
110
+ return self
111
+ end
112
+
113
+ built.operations.each do |operation|
114
+ operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = current }
115
+ end
116
+ current.add_port(built)
117
+ self
118
+ end
119
+
120
+ door.define_singleton_method(:method_missing) do |verb, *args, **kwargs, &block|
121
+ # A bare call starts a Privacy marking chain (see
122
+ # `BindingProxy#method_missing`), reached here when the door is already
123
+ # installed (a second in-process boot) rather than at parse time.
124
+ return Bluebook::DSL::AttributePath.new(fqn, [verb.to_s]) if args.empty? && kwargs.empty? && !block
125
+
126
+ collector = Bluebook::DSL::HecksagonBuilder.collector
127
+ world = Bluebook::DSL::WorldBuilder.current
128
+ # Inside a `.world` block the same qualified spelling records a world setting.
129
+ return world.record_binding(verb, args, kwargs, block) if world && !collector
130
+ return super(verb, *args, **kwargs, &block) unless collector
131
+
132
+ collector << Bluebook::Bind.new(
133
+ aggregate: fqn,
134
+ verb: verb.to_s,
135
+ adapter: args.first.to_s,
136
+ role: kwargs[:role]&.to_s
137
+ )
138
+ block&.call
139
+ self
140
+ end
141
+
142
+ door.define_singleton_method(:respond_to_missing?) do |name, include_private = false|
143
+ !Bluebook::DSL::HecksagonBuilder.collector.nil? || !Bluebook::DSL::WorldBuilder.current.nil? ||
144
+ super(name, include_private)
145
+ end
146
+
147
+ # Uses `aggregate.hecks_name`, not the qualified `fqn`: qualifying it here
148
+ # would make `Account::Debit`'s meaning depend on whether a stale door
149
+ # from an earlier boot happens to be sitting on this process.
150
+ door.define_singleton_method(:const_missing) do |name|
151
+ resolver = Bluebook::DSL::ConstShim.resolver
152
+ return resolver.call("#{aggregate.hecks_name}::#{name}") if resolver
153
+
154
+ super(name)
155
+ end
156
+
157
+ door
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,72 @@
1
+ require_relative "../../bluebook/dsl/binding_proxy"
2
+ require_relative "../../bluebook/dsl/const_shim"
3
+ require_relative "../../bluebook/dsl/hecksagon_builder"
4
+
5
+ module Hecks
6
+ module Doors
7
+ module RubyDoor
8
+ # One chapter's module: vision and aggregate list on the singleton, one
9
+ # aggregate door per declared head, and a `const_missing` hook for undeclared names.
10
+ module Chapter
11
+ # Builds the anonymous module that stands for one booted chapter: `vision`,
12
+ # `aggregates`, `docs`, `narrate` and `project` as singleton methods, plus one
13
+ # nested constant per aggregate holding that aggregate's door.
14
+ #
15
+ # @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
16
+ # dispatcher each aggregate door closes over
17
+ # @param bluebook [Bluebook::Chapter] the chapter to project into a module
18
+ # @return [Module] a fresh, unnamed module; `RubyDoor.install` gives it its
19
+ # top-level name
20
+ # @raise [NameError] if an aggregate's name is not a valid constant name
21
+ def chapter_module(dispatcher, bluebook)
22
+ chapter = Module.new
23
+ chapter.define_singleton_method(:vision) { bluebook.vision }
24
+ chapter.define_singleton_method(:aggregates) { bluebook.aggregates.map(&:name).sort }
25
+
26
+ # The chapter's usage document, projected from its IR on each call so it
27
+ # cannot go stale.
28
+ chapter.define_singleton_method(:docs) do |**options|
29
+ Projector.call(:docs, bluebook: bluebook, options: options)
30
+ end
31
+
32
+ # The chapter read back in english, via `Projector::NarrateProjector`.
33
+ chapter.define_singleton_method(:narrate) do |**options|
34
+ Projector.call(:narrate, bluebook: bluebook, options: options)
35
+ end
36
+
37
+ # Projects the chapter's IR through a target; `out:` writes the artifact and
38
+ # the remaining options go to the projector (`audience:` for OIDC).
39
+ #
40
+ # Pizzas.project(Projections::OIDC)
41
+ # Pizzas.project(Projections::Shape, out: "shape.json")
42
+ chapter.define_singleton_method(:project) do |target, out: nil, **options|
43
+ key = Projector.key_for(target)
44
+ artifact = Projector.call(key, bluebook: bluebook, options: options)
45
+ return artifact unless out
46
+
47
+ Projector.write(artifact, out, as: Projector.emits_for(key))
48
+ end
49
+
50
+ bluebook.aggregates.each do |aggregate|
51
+ chapter.const_set(aggregate.hecks_name, aggregate_module(dispatcher, bluebook.name, aggregate))
52
+ end
53
+
54
+ # Inside a hecksagon a name is a declaration: with a collector open it becomes
55
+ # a `BindingProxy`. Otherwise a scoped reference from a bluebook mid-declaration
56
+ # goes to the `ConstShim` resolver, so it resolves whether or not a facade exists.
57
+ chapter.define_singleton_method(:const_missing) do |name|
58
+ collector = Bluebook::DSL::HecksagonBuilder.collector
59
+ return Bluebook::DSL::BindingProxy.new("#{bluebook.name}::#{name}", collector) if collector
60
+
61
+ resolver = Bluebook::DSL::ConstShim.resolver
62
+ return resolver.call("#{bluebook.name}::#{name}") if resolver
63
+
64
+ super(name)
65
+ end
66
+
67
+ chapter
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,77 @@
1
+ require_relative "../chapters"
2
+ require_relative "ruby_door/chapter"
3
+ require_relative "ruby_door/aggregate_door"
4
+
5
+ module Hecks
6
+ module Doors
7
+ # The door without classes: anonymous per-boot modules whose singleton methods
8
+ # dispatch by FQN, installed by `Loader.bind_runtime` and replaced whole on the next boot.
9
+ #
10
+ # `persisted_by("Heki")` in a `.hecksagon` file lands on the module's `method_missing`,
11
+ # which records a `Bind` into the open `HecksagonBuilder.collector`.
12
+ module RubyDoor
13
+ # Names that would shadow the machinery a Handle runs on; a field with one gets no reader.
14
+ RESERVED = %i[id state events reload inspect to_h hash class].freeze
15
+
16
+ extend Chapter
17
+ extend AggregateDoor
18
+
19
+ module_function
20
+
21
+ # Installs one top-level module per booted chapter, and one per aggregate, each
22
+ # closing over `dispatcher`, so `Pizzas::Pizza` and the bare `Pizza` both open the
23
+ # door of the boot that ran last.
24
+ #
25
+ # A gem chapter a hecksagon `attaches` installs nothing (`Query`, `Port` stay free).
26
+ # An aggregate sharing its chapter's name gets no second constant. A name that user
27
+ # code or the stdlib already owns is left alone with a warning (see `Namespace.install`).
28
+ #
29
+ # @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
30
+ # dispatcher every installed door dispatches and queries through
31
+ # @return [Runtime::Dispatcher, Runtime::RemoteDispatcher] the same `dispatcher`
32
+ # @raise [NameError] if a chapter or aggregate name is not a valid constant name
33
+ def install(dispatcher)
34
+ dispatcher.registry.bluebooks.each_value do |bluebook|
35
+ next if attached_chapter?(dispatcher.registry, bluebook)
36
+
37
+ chapter = chapter_module(dispatcher, bluebook)
38
+ Namespace.install(*placement(bluebook), chapter)
39
+ # A namespaced chapter keeps its aggregates inside its namespace: top-level
40
+ # shortcuts would bring back the collisions the namespace exists to avoid.
41
+ next if bluebook.namespace
42
+
43
+ bluebook.aggregates.each do |aggregate|
44
+ next if aggregate.hecks_name == bluebook.name
45
+
46
+ Namespace.install(Object, aggregate.hecks_name, chapter.const_get(aggregate.hecks_name, false))
47
+ end
48
+ end
49
+ dispatcher
50
+ end
51
+
52
+ # Whether `bluebook` is a gem chapter that a hecksagon attached rather than a domain's own.
53
+ #
54
+ # @param registry [Runtime::Registry] the booted registry
55
+ # @param bluebook [Bluebook::Chapter] the chapter under test
56
+ # @return [Boolean]
57
+ def attached_chapter?(registry, bluebook)
58
+ registry.bounded?(bluebook.name) && Hecks::Chapters.index.key?(bluebook.name)
59
+ end
60
+
61
+ # Where a chapter's module installs: `Object::<name>`, or the constant path its
62
+ # `namespace` names, creating any missing parent modules along the way.
63
+ #
64
+ # @param bluebook [Bluebook::Chapter] the chapter being installed
65
+ # @return [Array(Module, String)] the parent module and the constant name within it
66
+ def placement(bluebook)
67
+ return [Object, bluebook.name] unless bluebook.namespace
68
+
69
+ *parents, leaf = bluebook.namespace.split("::")
70
+ parent = parents.reduce(Object) do |outer, name|
71
+ outer.const_defined?(name, false) ? outer.const_get(name, false) : outer.const_set(name, Module.new)
72
+ end
73
+ [parent, leaf]
74
+ end
75
+ end
76
+ end
77
+ end