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,103 +2,28 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # The interviewer — whatever asks the next good question, reads a
6
- # sentence back into proposed declarations, judges a model on taste
7
- # rather than structure, or suggests a name.
8
- #
9
- # ## Why a singleton port
10
- #
11
- # Resolved the same zero/one/many way every other port here is
12
- # (`Ports::IdentityGeneration`'s own singleton adapter — one
13
- # interviewer per process, never per-aggregate), because a second
14
- # adapter answering this port is exactly as unchoosable as a second
15
- # one minting identities.
16
- #
17
- # ## Why this exists
18
- #
19
- # Built last, on purpose, and still optional. `.claude/skills/
20
- # interview/SKILL.md` conducts a whole session with none of this —
21
- # Claude Code reads `bin/interview state` itself, asks the human
22
- # directly with real conversation context, and calls `bin/interview
23
- # ask`/`propose`/`accept` itself. This port exists for what that
24
- # cannot reach: a headless run (`bin/interview suggest`, no model in
25
- # the room otherwise), a batch `critique` over an already-written
26
- # chapter, and — the actual point of building it at all — a
27
- # scripted double (`spec/fixtures/scripted_agent.rb`) that makes the
28
- # whole loop testable with no real model involved.
29
- #
30
- # ## What this port is not
31
- #
32
- # It does not judge whether a declaration is well-formed — that is
33
- # the meta-domain's own job, answered by a real dispatch refusing or
34
- # not (`Interview::Session#offer`). This port only ever produces
35
- # shape: a question, a proposed declaration, a judgement about
36
- # taste, a name. A proposal naming a category the language does not
37
- # declare is an adapter fault, refused here, in `Answers`; a
38
- # proposal naming a real category but describing the wrong domain
39
- # fact is dispatched anyway, so the language gets to say why. That
40
- # line is the whole design.
41
- #
42
- # ## Where parsing happens
43
- #
44
- # Parsing belongs to this file, not the adapter. An adapter answers
45
- # with a plain, already-JSON-shaped Hash (a real model's parsed
46
- # reply, or a spec double's own hand-built one) — never a Struct —
47
- # so every adapter is validated identically here rather than trusting
48
- # each one to refuse the same way. Two adapters that parsed
49
- # differently would mean the same malformed answer passing through
50
- # one and refusing through the other.
5
+ # The interviewer: asks questions, reads prose into proposed declarations, critiques a
6
+ # model on taste, and suggests names. One adapter per process.
51
7
  module Agent
52
8
  NAME = "agent".freeze
53
9
 
54
- # The answer came back and could not be used — no JSON in it, a
55
- # category the language does not declare, a severity outside the
56
- # two that exist. A foreign failure (JSON::ParserError, a missing
57
- # key) wrapped into something this port owns, the same shape
58
- # `Ports::Authentication::ValidationError` already is, so no
59
- # caller ever rescues a raw parser error leaking out of an
60
- # adapter.
10
+ # The adapter's answer arrived but was unusable; retrying the same prompt will not help.
61
11
  class ValidationError < StandardError
62
12
  end
63
13
 
64
- # Nothing answered at all — the binary is missing, the subprocess
65
- # died, the call timed out. Separate from ValidationError on
66
- # purpose: unavailable means retry or fall back to asking the
67
- # human directly; malformed means the prompt is wrong, not the
68
- # transport, and retrying identically will not fix it.
14
+ # Nothing answered (missing binary, dead subprocess, timeout); retry or ask the human.
69
15
  class Unavailable < StandardError
70
16
  end
71
17
 
72
- # ── what the four operations hand back ──────────────────────────
73
- #
74
- # Structs, not hashes, for the reason `Bluebook::ModelCheck::Finding`
75
- # already is one: a `keyword_init` Struct raises on a key nobody
76
- # declared, which turns "the model invented a field" into a
77
- # failure at the boundary rather than a nil three calls in.
78
-
79
- # One question. `because` is the reasoning quoted back so a human
80
- # can see it, not decoration — the same "show your work" the
81
- # language's own refusal messages already practice.
18
+ # keyword_init Structs raise on an undeclared key, so an invented field fails at the edge.
19
+
20
+ # One question; `because` is the reasoning shown to the human.
82
21
  Question = Struct.new(:text, :because, keyword_init: true)
83
22
 
84
- # One proposed declaration, already shaped as
85
- # `Interview::Proposal`'s own `Argument` rows — `{name:, field:,
86
- # value:}`, the exact triple `bin/interview propose --arg
87
- # name:field:value` already takes and `Interview::Lowering`
88
- # already knows how to lower. Nothing here decides how to address
89
- # a record or whether a value is bare or wrapped — that was
90
- # already the proposal-writer's job in `interview.bluebook`'s own
91
- # design (see `Argument`'s own comment there); this only adds the
92
- # prose reasoning a human typed does not carry on its own.
23
+ # `arguments` are `{name:, field:, value:}` rows, as `bin/interview propose --arg` takes.
93
24
  Proposal = Struct.new(:verb, :arguments, :rationale, keyword_init: true)
94
25
 
95
- # Critique reuses `Bluebook::ModelCheck::Finding`'s own shape —
96
- # same fields, same severities, so a mechanical finding
97
- # (`Session#gaps`) and a judgement (this) print in one list and
98
- # sort together. The kind vocabulary is not shared — ModelCheck's
99
- # eleven kinds are structural facts about a graph; these are
100
- # opinions about a model, closed here on purpose (an open kind
101
- # field is an open prompt, and an open prompt drifts).
26
+ # Kinds are closed: an open kind is an open prompt, and an open prompt drifts.
102
27
  CRITIQUE_KINDS = %i[
103
28
  anemic_aggregate wrong_boundary crud_verb leaky_value_object
104
29
  missing_lifecycle missing_invariant ubiquitous_language
@@ -106,132 +31,82 @@ module Hecks
106
31
  ].freeze
107
32
  SEVERITIES = %i[error warning].freeze
108
33
 
34
+ # Same shape as `Bluebook::ModelCheck::Finding`, so gaps and critiques sort together.
109
35
  Finding = Struct.new(:kind, :severity, :subject, :message, keyword_init: true) do
110
36
  def to_s = "#{severity.to_s.upcase.ljust(7)} #{kind.to_s.ljust(20)} #{subject} — #{message}"
111
37
  end
112
38
 
113
- # One suggested name. `rejected` carries the near-misses and why
114
- # they were passed over — free at the point the model is choosing
115
- # anyway, and the part a human actually learns from.
39
+ # `rejected` holds the near-misses and why each was passed over.
116
40
  Suggestion = Struct.new(:name, :because, :rejected, keyword_init: true)
117
41
 
42
+ # Adapters return plain Hashes; validating here makes every adapter refuse the same way.
118
43
  module_function
119
44
 
120
- # Asks the adapter for the next best question and validates its raw answer into structs.
121
- #
122
- # `state` is the whole picture — normally
123
- # `Interview::Session#declaration` plus `#gaps`, so an adapter
124
- # needs no memory of its own between calls; that is what lets a
125
- # headless run be a series of one-shot processes, same as
126
- # `bin/interview` itself already is.
45
+ # Asks the adapter for the next question.
127
46
  #
128
47
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
129
- # @param state [Hash] the interview's whole current picture (declaration plus gaps),
130
- # JSON-able because an adapter may serialise it into a prompt
131
- # @param asked [Array<Object>] JSON-able record of the questions already asked, so the
132
- # adapter does not repeat one; `[]` when nothing has been asked
133
- # @return [Array<Ports::Agent::Question>] the questions the adapter answered with, in
134
- # its order; `[]` if it offered none
135
- # @raise [Ports::Agent::ValidationError] if the answer is not a Hash holding a
136
- # `"questions"` array whose rows each carry a non-blank `"text"` and `"because"`
137
- # @raise [Ports::Agent::Unavailable] if the adapter cannot answer at all (missing
138
- # binary, failed subprocess, timeout, or an exhausted scripted queue)
139
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
140
- # (see `adapter`)
48
+ # @param state [Hash] declaration plus gaps; adapters keep no memory between calls
49
+ # @param asked [Array<Object>] questions already asked, so the adapter does not repeat one
50
+ # @return [Array<Ports::Agent::Question>]
51
+ # @raise [Ports::Agent::ValidationError] unless the answer is a Hash whose `"questions"`
52
+ # rows each carry a non-blank `"text"` and `"because"`
53
+ # @raise [Ports::Agent::Unavailable] if the adapter cannot answer
54
+ # @raise [Runtime::WiringError] unless exactly one adapter implements the port
141
55
  def ask(registry, state:, asked: [])
142
56
  Answers.questions(adapter(registry).ask(state: state, asked: asked))
143
57
  end
144
58
 
145
- # Turns a human's sentence into proposed declarations, validated into structs.
146
- #
147
- # Returns `[]` when the sentence
148
- # carried no declaration at all (a clarifying question back from
149
- # the human, say) — a legitimate answer, not a failure.
59
+ # Turns a sentence into proposed declarations; `[]` when it named none.
150
60
  #
151
61
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
152
62
  # @param prose [String] a human's plain-English sentence
153
- # @param state [Hash] the interview's whole current picture, JSON-able because an
154
- # adapter may serialise it into a prompt
155
- # @return [Array<Ports::Agent::Proposal>] one proposal per declaration the sentence
156
- # named; `[]` when it named none
157
- # @raise [Ports::Agent::ValidationError] if the answer is not a Hash holding a
158
- # `"proposals"` array, a row's `"verb"` is not `Chapter::Aggregate.Command`, its
159
- # `"rationale"` is blank, or one of its argument rows has no `"name"`
160
- # @raise [Ports::Agent::Unavailable] if the adapter cannot answer at all (missing
161
- # binary, failed subprocess, timeout, or an exhausted scripted queue)
162
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
163
- # (see `adapter`)
63
+ # @param state [Hash] declaration plus gaps
64
+ # @return [Array<Ports::Agent::Proposal>]
65
+ # @raise [Ports::Agent::ValidationError] unless the answer is a Hash whose `"proposals"`
66
+ # rows have a `Chapter::Aggregate.Command` verb, a rationale and named arguments
67
+ # @raise [Ports::Agent::Unavailable] if the adapter cannot answer
68
+ # @raise [Runtime::WiringError] unless exactly one adapter implements the port
164
69
  def interpret(registry, prose:, state:)
165
70
  Answers.proposals(adapter(registry).interpret(prose: prose, state: state))
166
71
  end
167
72
 
168
- # Asks the adapter to judge a declared model on taste, validated into structs.
169
- #
170
- # What is wrong with this as a model — handed everything already
171
- # known (the language's own refusals, `Session#gaps`'s mechanical
172
- # findings) so it spends its judgement on what neither of those
173
- # can see, rather than restating them.
73
+ # Asks the adapter to judge a declared model on taste.
174
74
  #
175
75
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
176
- # @param declared [Hash] the chapter as declared so far, JSON-able because an adapter
177
- # may serialise it into a prompt
178
- # @param refusals [Array<Object>] JSON-able refusals the language itself already
179
- # raised; `[]` when there are none
180
- # @param findings [Array<Object>] JSON-able mechanical findings `Session#gaps` already
181
- # found; `[]` when there are none
182
- # @return [Array<Ports::Agent::Finding>] the adapter's judgements; `[]` when it has
183
- # nothing worth saying
184
- # @raise [Ports::Agent::ValidationError] if the answer is not a Hash holding a
185
- # `"findings"` array, a row's `"kind"` is outside `CRITIQUE_KINDS`, its `"severity"`
186
- # is outside `SEVERITIES`, or its `"subject"` or `"message"` is blank
187
- # @raise [Ports::Agent::Unavailable] if the adapter cannot answer at all (missing
188
- # binary, failed subprocess, timeout, or an exhausted scripted queue)
189
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
190
- # (see `adapter`)
76
+ # @param declared [Hash] the chapter as declared so far
77
+ # @param refusals [Array<Object>] refusals the language already raised
78
+ # @param findings [Array<Object>] `Session#gaps` findings; both are passed so the
79
+ # adapter spends its judgement on what neither can see
80
+ # @return [Array<Ports::Agent::Finding>]
81
+ # @raise [Ports::Agent::ValidationError] if a kind is outside `CRITIQUE_KINDS` or a
82
+ # severity outside `SEVERITIES`
83
+ # @raise [Ports::Agent::Unavailable] if the adapter cannot answer
191
84
  def critique(registry, declared:, refusals: [], findings: [])
192
85
  Answers.findings(adapter(registry).critique(declared: declared, refusals: refusals, findings: findings))
193
86
  end
194
87
 
195
- # Asks the adapter to suggest a name for a construct, validated into structs.
196
- #
197
- # Vocabulary help. `near` is what the chapter already calls
198
- # things, so a suggestion cannot collide with a name in use.
88
+ # Suggests names for a construct.
199
89
  #
200
- # Named `suggest_name`, not `name` — the plan's own word for this
201
- # operation, but `Module#name` already exists and is load-bearing
202
- # everywhere (backtraces, RSpec's own description building,
203
- # `inspect`): a module-function called `name` shadows it the
204
- # instant it's defined, and `SomeModule.name` (no args) then
205
- # raises `ArgumentError: missing keywords` the next time anything
206
- # — not this file, something else entirely — asks the module its
207
- # own name. Measured, not theoretical: this exact collision broke
208
- # RSpec's own failure-message formatting the first time it was
209
- # named `name` here.
90
+ # Not called `name`: a module function of that name shadows `Module#name`.
210
91
  #
211
92
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
212
93
  # @param meaning [String] what the new name needs to mean
213
- # @param kind [String] the kind of construct being named, such as `"event"`; an
214
- # adapter interpolates it into its prompt
215
- # @param near [Array<String>] names already in use in this chapter, which a suggestion
216
- # must not collide with; `[]` when there are none
217
- # @return [Array<Ports::Agent::Suggestion>] the suggested names, each with its
218
- # `rejected` near-misses as Strings
219
- # @raise [Ports::Agent::ValidationError] if the answer is not a Hash holding a
220
- # `"names"` array whose rows each carry a non-blank `"name"` and `"because"`
221
- # @raise [Ports::Agent::Unavailable] if the adapter cannot answer at all (missing
222
- # binary, failed subprocess, timeout, or an exhausted scripted queue)
223
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
224
- # (see `adapter`)
94
+ # @param kind [String] the construct being named, such as `"event"`
95
+ # @param near [Array<String>] names already in use; a suggestion must not collide
96
+ # @return [Array<Ports::Agent::Suggestion>]
97
+ # @raise [Ports::Agent::ValidationError] unless the answer is a Hash whose `"names"`
98
+ # rows each carry a non-blank `"name"` and `"because"`
99
+ # @raise [Ports::Agent::Unavailable] if the adapter cannot answer
225
100
  def suggest_name(registry, meaning:, kind:, near: [])
226
101
  Answers.suggestions(adapter(registry).suggest_name(meaning: meaning, kind: kind, near: near))
227
102
  end
228
103
 
229
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
104
+ # Finds the single adapter bound to this port.
230
105
  #
231
106
  # @param registry [Runtime::Registry] the booted registry to search
232
107
  # @return [Module] the adapter module or class implementing this port
233
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
234
- # or the one that does has no Ruby implementation under `Hecks::Adapters`
108
+ # @raise [Runtime::WiringError] if none, or more than one, implements the port, or the
109
+ # one that does has no Ruby implementation under `Hecks::Adapters`
235
110
  def adapter(registry)
236
111
  implementations = registry.adapters.values.select { |a| a.port == NAME }
237
112
 
@@ -2,27 +2,12 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # The OIDC handshake itself — building the URL a browser goes to,
6
- # and turning the code a provider sends back into a Hash of verified
7
- # claims (`issuer`, `subject`, `email`, `email_verified`). Resolved the same way every
8
- # other port here resolves its adapter: one adapter registry-wide
9
- # answers this, not a per-aggregate binding, since a domain has no
10
- # reason to want a different sign-in provider per aggregate.
11
- #
12
- # The other half of "who is this" — what a verified pair means to
13
- # this app, whether it resolves to an existing Identity — is
14
- # `Ports::IdentityResolution`'s job, not this one's. This port only
15
- # ever talks to the external provider; it never touches the
16
- # registry's own Identity/Governance data (it takes `registry`
17
- # purely to resolve which adapter answers it, same as every port
18
- # here already does).
5
+ # The OIDC handshake: builds the provider URL and turns the returned code into verified claims.
6
+ # One adapter registry-wide answers it; it never touches the registry's Identity data.
19
7
  module Authentication
20
8
  NAME = "authentication".freeze
21
9
 
22
- # A sign-in that could not be verified — a state mismatch, a failed code
23
- # exchange, a missing or invalid ID token. An adapter wraps its own
24
- # libraries' errors into this, so a caller rescues one class whichever
25
- # provider answers the port.
10
+ # A sign-in that could not be verified (state mismatch, failed code exchange, bad ID token).
26
11
  class ValidationError < StandardError
27
12
  end
28
13
 
@@ -30,17 +15,13 @@ module Hecks
30
15
 
31
16
  # Builds the provider URL that starts a sign-in, with the CSRF state minted for it.
32
17
  #
33
- # The caller keeps the state (in a session, typically) and hands it back to `verify`
34
- # as `expected_state`.
18
+ # The caller keeps the state and hands it back to `verify` as `expected_state`.
35
19
  #
36
20
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
37
21
  # @return [Array(String, String)] the URL to send the browser to, then the fresh
38
22
  # `state` value embedded in it
39
23
  # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
40
- # (see `adapter`)
41
24
  # @raise [KeyError] if the adapter's required configuration is unset
42
- # (`GoogleAuthentication` reads `GOOGLE_CLIENT_ID`, `GOOGLE_CLIENT_SECRET` and
43
- # `GOOGLE_REDIRECT_URI` with no defaults)
44
25
  def authorization_url(registry)
45
26
  adapter(registry).authorization_url
46
27
  end
@@ -50,28 +31,20 @@ module Hecks
50
31
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
51
32
  # @param code [String] the authorization code the provider sent back
52
33
  # @param state [String, nil] the state parameter the provider returned; nil is refused
53
- # @param expected_state [String, nil] the state `authorization_url` handed out before
54
- # the redirect; nil is refused
55
- # @return [Hash{Symbol => Object}] the verified claims: `issuer:` and `subject:`
56
- # (String), `email:` (String, or nil if the token carries none) and
57
- # `email_verified:` (Boolean) — never the raw token
58
- # @raise [Ports::Authentication::ValidationError] if either state is nil or the two
59
- # differ, the code exchange fails, the response has no ID token, or the ID token
60
- # does not verify
34
+ # @param expected_state [String, nil] the state `authorization_url` returned; nil is refused
35
+ # @return [Hash{Symbol => Object}] the verified claims: `issuer:`, `subject:`, `email:`
36
+ # (nil if the token carries none) and `email_verified:` -- never the raw token
37
+ # @raise [Ports::Authentication::ValidationError] if a state is nil or they differ, the
38
+ # code exchange fails, or the ID token is missing or does not verify
61
39
  # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
62
- # (see `adapter`)
63
- # @raise [KeyError] if the adapter's required configuration is unset, or a verified
64
- # token lacks an `iss` or `sub` claim
40
+ # @raise [KeyError] if required configuration is unset, or the token lacks `iss`/`sub`
65
41
  def verify(registry, code:, state:, expected_state:)
66
42
  adapter(registry).verify(code: code, state: state, expected_state: expected_state)
67
43
  end
68
44
 
69
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
45
+ # Finds the single adapter bound to this port.
70
46
  #
71
- # @param registry [Runtime::Registry] the booted registry to search
72
- # @return [Module] the adapter module or class implementing this port
73
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
74
- # or the one that does has no Ruby implementation under `Hecks::Adapters`
47
+ # @raise [Runtime::WiringError] if none, or more than one, implements this port
75
48
  def adapter(registry)
76
49
  implementations = registry.adapters.values.select { |a| a.port == NAME }
77
50
 
@@ -2,28 +2,8 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # Two yes/no questions and one value an application asks before
6
- # binding a caller — resolved the same way `Ports::IdentityGeneration`
7
- # resolves its own adapter: one adapter registry-wide answers this
8
- # port, not a per-aggregate binding, since a domain has no reason to
9
- # want a different authorization source per aggregate. What answers
10
- # it is deliberately not named here — the governance-backed adapter
11
- # is one implementation, not the only possible one, the same way
12
- # `SequentialIdentity` and `SecureRandomIdentity` are two
13
- # implementations of `identity_generation`.
14
- #
15
- # A caller decides what to do with the answer — dispatch under that
16
- # role, refuse, log, prefer it over some other fallback value — this
17
- # only answers the question asked. Nothing here binds a
18
- # `Runtime::Caller`.
19
- #
20
- # `CommandRules::Authorization#refuse_role_mismatch` calls `holds_role?`
21
- # directly, once a caller binds an `actor_id` and the command's domain
22
- # has Governance attached (see that rule's own header). `spec/
23
- # act_as_spec.rb` remains the precedent for the other shape — two
24
- # separate registries, queried directly by name — for whenever
25
- # Governance is not in the same boot as the caller; this port is the
26
- # same questions asked through one adapter when it is.
5
+ # Role questions an application asks before binding a caller. One adapter registry-wide
6
+ # answers them; it only answers, and never binds a `Runtime::Caller`.
27
7
  module Authorization
28
8
  NAME = "authorization".freeze
29
9
 
@@ -35,15 +15,11 @@ module Hecks
35
15
  # @param actor_id [String] the actor whose grants are checked
36
16
  # @param role [String, Symbol] the role name to look for, compared as a String
37
17
  # @param as_of [Integer, nil] Unix epoch seconds (from `Ports::Clock.now`); a grant whose
38
- # `starts_at` is later, or does not parse as a time, does not count. nil skips the
39
- # `starts_at` check entirely
40
- # @param scope [String, nil] the scope the caller acts in; only a grant made for that
41
- # scope counts. nil skips the scope check, so a grant in any scope counts
42
- # @return [Boolean] true if at least one live grant of `role` to `actor_id` passes the
43
- # `as_of` and `scope` checks
44
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
45
- # (see `adapter`), or the governance-backed adapter finds no single loaded chapter
46
- # providing `"authorization"`
18
+ # `starts_at` is later, or does not parse as a time, does not count. nil skips the check
19
+ # @param scope [String, nil] only a grant made for this scope counts; nil counts any scope
20
+ # @return [Boolean] true if at least one live grant of `role` to `actor_id` passes
21
+ # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter,
22
+ # or the governance-backed adapter finds no single chapter providing `"authorization"`
47
23
  def holds_role?(registry, actor_id:, role:, as_of: nil, scope: nil)
48
24
  adapter(registry).holds_role?(registry, actor_id: actor_id, role: role, as_of: as_of, scope: scope)
49
25
  end
@@ -56,32 +32,29 @@ module Hecks
56
32
  # String
57
33
  # @return [Boolean] true if a live (not ended) allowance lets `from_role` act as
58
34
  # `to_role`
59
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
60
- # (see `adapter`), or the governance-backed adapter finds no single loaded chapter
61
- # providing `"authorization"`
35
+ # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter,
36
+ # or the governance-backed adapter finds no single loaded chapter providing
37
+ # `"authorization"`
62
38
  def authorized_as?(registry, from_role:, to_role:)
63
39
  adapter(registry).authorized_as?(registry, from_role: from_role, to_role: to_role)
64
40
  end
65
41
 
66
- # Looks up the role an actor holds right now, rather than checking a guessed one.
42
+ # Looks up the role an actor holds right now.
67
43
  #
68
44
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
69
45
  # @param actor_id [String] the actor to look up
70
46
  # @return [String, nil] the role name of the actor's first live (not ended) grant, or
71
47
  # nil if it has none; the caller supplies any fallback
72
- # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
73
- # (see `adapter`), or the governance-backed adapter finds no single loaded chapter
74
- # providing `"authorization"`
48
+ # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter,
49
+ # or the governance-backed adapter finds no single loaded chapter providing
50
+ # `"authorization"`
75
51
  def live_role_for(registry, actor_id:)
76
52
  adapter(registry).live_role_for(registry, actor_id: actor_id)
77
53
  end
78
54
 
79
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
55
+ # Finds the single adapter bound to this port.
80
56
  #
81
- # @param registry [Runtime::Registry] the booted registry to search
82
- # @return [Module] the adapter module or class implementing this port
83
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
84
- # or the one that does has no Ruby implementation under `Hecks::Adapters`
57
+ # @raise [Runtime::WiringError] if none, or more than one, implements this port
85
58
  def adapter(registry)
86
59
  implementations = registry.adapters.values.select { |a| a.port == NAME }
87
60
 
@@ -2,42 +2,8 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # What time it is — the one fact a domain cannot derive and must not invent.
6
- #
7
- # Resolved exactly the way `Ports::IdentityGeneration` resolves its own
8
- # adapter: one adapter registry-wide implements this, not a per-aggregate
9
- # binding, because two aggregates in one running app have no real reason to
10
- # disagree about the time.
11
- #
12
- # ## Why a port and not `Time.now`
13
- #
14
- # A staleness rule — "another agent may take this claim after fifteen
15
- # minutes" — is untestable against the real clock: a spec for it would
16
- # either sleep for fifteen minutes or never run at all. Bound to a fixed
17
- # adapter, the same rule is three lines. That is the whole argument, and
18
- # it is the same one `SequentialIdentity` makes next door.
19
- #
20
- # ## Why a predicate still can't ask the time
21
- #
22
- # The expression sublanguage has no clock and should not: a `given` that
23
- # read the time would evaluate differently on two runs over the same
24
- # record, and every replay, audit and fuzz oracle in this repository
25
- # assumes it does not. So `now` remains an argument the predicate merely
26
- # reads, and this port is what lets a caller stop typing it — the door
27
- # fills it in, the value is baked into the dispatch, and the recorded
28
- # step carries the concrete number forever after.
29
- #
30
- # ## Why the runtime never calls this directly
31
- #
32
- # `IdentityGeneration`'s own note works through the replay question for
33
- # a minted uuid and lands on "the value gets baked into the caller's
34
- # args at the first live dispatch". A clock consulted inside the
35
- # interpreter would not have that property: a recorded corpus step
36
- # replayed tomorrow would silently get tomorrow's time, and the
37
- # fuzzer's oracle and the adapter-agreement gate both compare runs of
38
- # exactly that shape. So the filling happens at the door, where a
39
- # human or an agent is typing, and never on the dispatch path a replay
40
- # uses.
5
+ # What time it is, as one registry-wide adapter answers it.
6
+ # Predicates cannot read the clock (replays must be deterministic), so the door fills `now`.
41
7
  module Clock
42
8
  NAME = "clock".freeze
43
9
 
@@ -45,23 +11,17 @@ module Hecks
45
11
 
46
12
  # Reads the current time from the bound clock adapter.
47
13
  #
48
- # Seconds, as an integer, because that is what the sublanguage can do
49
- # arithmetic on. `claimed_at.value + window.value <= now.value` is
50
- # addition and comparison — the only two things it has — and a Time
14
+ # Integer seconds, because the expression sublanguage can add and compare but a Time
51
15
  # object supports neither.
52
16
  #
53
17
  # @param registry [Runtime::Registry] the booted registry to resolve the adapter against
54
18
  # @return [Integer] the current time, in Unix epoch seconds
55
19
  # @raise [Runtime::WiringError] if this port does not resolve to exactly one adapter
56
- # (see `adapter`)
57
20
  def now(registry) = adapter(registry).now
58
21
 
59
- # Finds the single adapter bound to this port, refusing an ambiguous wiring.
22
+ # Finds the single adapter bound to this port.
60
23
  #
61
- # @param registry [Runtime::Registry] the booted registry to search
62
- # @return [Module] the adapter module or class implementing this port
63
- # @raise [Runtime::WiringError] if no adapter, or more than one, implements this port,
64
- # or the one that does has no Ruby implementation under `Hecks::Adapters`
24
+ # @raise [Runtime::WiringError] if none, or more than one, implements this port
65
25
  def adapter(registry)
66
26
  implementations = registry.adapters.values.select { |a| a.port == NAME }
67
27
 
@@ -2,10 +2,8 @@ require_relative "../runtime/registry"
2
2
 
3
3
  module Hecks
4
4
  module Ports
5
- # The `extraction` port: resolves whichever adapter can recover a
6
- # predicate's own source (`canonical`). Reads `Hecks.current_registry`
7
- # directly rather than taking a registry argument, since extraction only
8
- # ever happens while a bluebook is loading, never after boot.
5
+ # Resolves the adapter that recovers a predicate's own source (`canonical`).
6
+ # Reads `Hecks.current_registry`, since extraction only happens while a bluebook loads.
9
7
  module Extraction
10
8
  NAME = "extraction".freeze
11
9
 
@@ -16,19 +14,16 @@ module Hecks
16
14
  # @param block [Proc] a block written in a bluebook file, such as a `given` predicate
17
15
  # or an `identified_by` path
18
16
  # @return [String, nil] the block body's source, normalised by
19
- # `Bluebook::Expression::CanonicalForm` (whitespace collapsed, linked replacements
20
- # applied); nil if the block's file cannot be read, no block starts on its line, or
21
- # the block has an empty body
17
+ # `Bluebook::Expression::CanonicalForm`; nil if the block's file cannot be read, no
18
+ # block starts on its line, or the block has an empty body
22
19
  # @raise [Runtime::WiringError] if called outside a boot, or this port does not resolve
23
- # to exactly one adapter (see `adapter`)
20
+ # to exactly one adapter
24
21
  def canonical(block) = adapter.canonical(block)
25
22
 
26
23
  # Finds the single adapter bound to this port in the registry currently booting.
27
24
  #
28
- # @return [Module] the adapter module or class implementing this port
29
- # @raise [Runtime::WiringError] if `Hecks.current_registry` is nil (resolved outside a
30
- # boot), if no adapter, or more than one, implements this port, or if the one that
31
- # does has no Ruby implementation under `Hecks::Adapters`
25
+ # @raise [Runtime::WiringError] if called outside a boot, or none, or more than one,
26
+ # implements this port
32
27
  def adapter
33
28
  registry = Hecks.current_registry
34
29
  unless registry