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
@@ -3,58 +3,135 @@ require_relative "../../hecks"
3
3
 
4
4
  module Hecks
5
5
  module CLI
6
- # The command behind `bin/project_cli` and `hecks project_cli`: writes a
6
+ # The command behind `hecks project_cli` and `hecks project_cli`: writes a
7
7
  # command-line launcher beside each domain, named after its bluebook, so
8
8
  # `Hecks.bluebook "QualityControl"` in `qa/` becomes `qa/quality_control`.
9
9
  #
10
- # ## A launcher, not a CLI
10
+ # Each launcher is a dozen lines pinning one directory and handing over to
11
+ # `Doors::CliRunner`; the surface itself is projected at the moment it runs,
12
+ # so editing a chapter changes behaviour without regenerating anything.
11
13
  #
12
- # Each file is a dozen lines pinning one directory and handing over to
13
- # `Facade::CliRunner`. The surface still comes from `Projector.call(:cli, …)` at
14
- # the moment it runs, so editing a chapter changes the launcher's behaviour
15
- # without regenerating anything. Re-run this when a domain is added or renamed.
16
- #
17
- # ## Beside the domain
18
- #
19
- # A domain's command line lives with the domain, so a folder is the whole unit.
20
- # The launcher boots `__dir__`, and reaches `lib` by counting how deep the domain
21
- # sits below the root, so no line knows where the checkout was cloned.
14
+ # A chapter whose world's `launcher` setting names an `executable` gets its launcher
15
+ # there instead: the Hecks chapter's is the gem's `exe/hecks`.
22
16
  module ProjectCli
23
17
  # Build output and other trees under a root that hold no domain a caller means.
24
18
  IGNORED = %r{\A(rust|deploy|tmp|coverage)/}
25
19
 
20
+ # What a chapter name, a domain path and a launcher verb may be made of.
21
+ NAME = /\A[A-Za-z][A-Za-z0-9_ ]*\z/
22
+ PATH = %r{\A[\w./-]+\z}
23
+ VERB = /\A[A-Za-z_][A-Za-z0-9_]*\z/
24
+
25
+ # Set first in an opted-in launcher, before anything reads a file.
26
+ ENCODING = "Encoding.default_external = Encoding::UTF_8\nEncoding.default_internal = Encoding::UTF_8\n\n".freeze
27
+
28
+ # How every launcher ends.
29
+ PLAIN_ENDING = "status.zero? ? puts(text) : abort(text)".freeze
30
+
31
+ # How an opted-in launcher ends: a failed `--wait` run still prints its settled record.
32
+ OPTED_ENDING = <<~LAUNCHER_TAIL.chomp.freeze
33
+ # A `--wait` run that failed answers its settled record on stdout, so `| jq` reads it
34
+ # either way, and says why on stderr.
35
+ if reason
36
+ puts text
37
+ warn reason
38
+ exit status
39
+ end
40
+ status.zero? ? puts(text) : abort(text)
41
+ LAUNCHER_TAIL
42
+
43
+ # The generator's name as an executable launcher's header states it, whoever ran it.
44
+ GENERATOR = "hecks project_cli".freeze
45
+
26
46
  module_function
27
47
 
28
- # Writes a launcher for each domain `argv` names, or for every domain under
29
- # `root`.
48
+ # Writes a launcher for each named domain, or for every domain under `root`.
30
49
  #
31
- # @param argv [Array<String>] domain paths relative to `root`; empty for all of them
32
- # @param program [String] the name the generated header credits
33
- # @param root [String] the directory domains are found under and paths resolve against
34
- # @param remove_stale_bin [Boolean] whether to delete `root/bin/<name>`, where a
35
- # launcher for the same chapter would otherwise linger as a second front door
50
+ # `--check` writes nothing and exits 1 when a launcher differs from the one this would
51
+ # write. A domain that cannot boot has none to compare, so it fails too.
52
+ #
53
+ # @param argv [Array<String>] domain paths under `root`, and optionally `--check`
54
+ # @param program [String] how the caller was invoked, named in a launcher's header
55
+ # @param root [String] the directory launchers are written under
56
+ # @param remove_stale_bin [Boolean] delete `root/bin/<name>`, a second front door
36
57
  # @return [void]
58
+ # @raise [SystemExit] with status 1 for a launcher out of date, an unreadable domain, a
59
+ # path outside `root` or an unknown flag
37
60
  def call(argv, program:, root:, remove_stale_bin: true)
38
- wanted = argv.empty? ? domains(root) : argv.map { |path| path.delete_prefix("#{root}/").chomp("/") }
61
+ flags, paths = argv.partition { |word| word.start_with?("-") }
62
+ unknown = flags - ["--check"]
63
+ abort "hecks project_cli: unknown option #{unknown.first} (the only option is --check)" unless unknown.empty?
39
64
 
40
- wanted.each do |path|
41
- name = bluebook_name(root, path) or next
42
- snake = Naming.snake(name)
43
- file = File.join(root, path, snake)
65
+ check = flags.include?("--check")
66
+ wanted = paths.empty? ? domains(root) : paths.map { |path| under_root(root, path) }
44
67
 
45
- File.write(file, launcher(path, name, program))
46
- FileUtils.chmod("+x", file)
47
- FileUtils.rm_f(File.join(root, "bin", snake)) if remove_stale_bin
68
+ outcomes = wanted.to_h { |path| [path, one(root, path, program, check, remove_stale_bin)] }
69
+ drifted = outcomes.select { |_, outcome| outcome == :drifted }.keys
70
+ failed = outcomes.select { |_, outcome| outcome == :failed }.keys
71
+ return if drifted.empty? && failed.empty?
48
72
 
49
- puts " #{path}/#{snake} -> #{name}"
50
- end
73
+ warn "launcher out of date for: #{drifted.join(', ')}; run `hecks project_cli #{drifted.join(' ')}`" unless drifted.empty?
74
+ warn "no launcher could be checked or written for: #{failed.join(', ')}" unless failed.empty?
75
+ exit 1
51
76
  end
52
77
 
53
- # Finds every domain under `root` a launcher can be written for.
78
+ # A domain path as a path under `root`.
54
79
  #
55
- # @param root [String] the directory to search under
56
- # @return [Array<String>] domain directory paths relative to `root`,
57
- # deduplicated and sorted
80
+ # @param root [String] the directory launchers are written under
81
+ # @param path [String] the path as typed, relative to `root` or absolute
82
+ # @return [String] the path relative to `root`
83
+ # @raise [SystemExit] when the path is outside `root`
84
+ def under_root(root, path)
85
+ expanded = File.expand_path(path, root)
86
+ inside = expanded == root || expanded.start_with?("#{root}/")
87
+ abort "hecks project_cli: #{path.inspect} is outside #{root}" unless inside
88
+
89
+ relative = expanded.delete_prefix(root).delete_prefix("/")
90
+ relative.empty? ? "." : relative
91
+ end
92
+
93
+ # @api private
94
+ # @return [Symbol] `:current` when the launcher is (or was made) as generated, `:drifted`
95
+ # when `check` found it out of date, `:failed` when the domain could not be read or its
96
+ # launcher could not be made
97
+ def one(root, path, program, check, remove_stale_bin)
98
+ runtime = Hecks.boot(File.join(root, path), install_doors: false)
99
+ name = runtime.registry.bluebooks.keys.first or raise "it loads no bluebook"
100
+ setting = Doors::LauncherOptions.settings(runtime, name) || {}
101
+ snake = Naming.snake(name)
102
+ executable = setting[:executable]
103
+ label = executable || "#{path}/#{snake}"
104
+ file = File.join(root, label)
105
+ text = launcher(path, name, program, executable: executable, legacy: setting[:legacy],
106
+ opted: !setting.empty?)
107
+ return skip(path, "#{label} is a directory") if File.directory?(file)
108
+
109
+ return :drifted if check && !(File.file?(file) && File.read(file) == text)
110
+
111
+ unless check
112
+ File.write(file, text)
113
+ FileUtils.chmod("+x", file)
114
+ FileUtils.rm_f(File.join(root, "bin", snake)) if remove_stale_bin && !executable
115
+ end
116
+ puts " #{label} -> #{name}"
117
+ :current
118
+ rescue StandardError => e
119
+ refuse(path, "cannot boot — #{e.message.lines.first.to_s.strip}")
120
+ end
121
+
122
+ # @api private
123
+ # @return [Symbol] `:current`: a directory where the launcher would go has nothing to check
124
+ def skip(path, reason)
125
+ warn " #{path}: #{reason}; no launcher written"
126
+ :current
127
+ end
128
+
129
+ # @api private
130
+ def refuse(path, reason)
131
+ warn " #{path}: #{reason}"
132
+ :failed
133
+ end
134
+
58
135
  def domains(root)
59
136
  folder = Adapters::Folder.new
60
137
  Dir.glob(File.join(root, "**/*.hecksagon"))
@@ -65,30 +142,41 @@ module Hecks
65
142
  .uniq.sort
66
143
  end
67
144
 
68
- # Boots the domain to read its declared name, which comes from
69
- # `Hecks.bluebook "…"` rather than the directory, so a domain renamed with
70
- # `formerly_known_as` gets a launcher under its new name.
71
- #
72
- # @param root [String] the directory `path` is relative to
73
- # @param path [String] a domain directory path
74
- # @return [String, nil] the domain's declared bluebook name, or nil after warning
75
- # when it fails to boot
76
- def bluebook_name(root, path)
77
- Hecks.boot(File.join(root, path), install_facade: false).registry.bluebooks.keys.first
78
- rescue StandardError => e
79
- warn " #{path}: cannot boot — #{e.message.lines.first.strip}"
80
- nil
81
- end
82
-
83
- # Renders one domain's launcher.
84
- #
85
- # @param path [String] the domain directory path, relative to the root
86
- # @param name [String] the domain's declared bluebook name
87
- # @param program [String] the name the generated header credits
88
- # @return [String] the launcher script's full source
89
- def launcher(path, name, program)
145
+ # The source of one launcher; names and paths go in as they are, so each must be plain.
146
+ # An `opted` one also sets UTF-8 and prints a failed `--wait` record on stdout.
147
+ # @param path [String] the domain's directory under the root
148
+ # @param name [String] the chapter's name
149
+ # @param program [String] the generator's invocation, named in the header
150
+ # @param executable [String, nil] the file's path under the root when it is not beside the
151
+ # domain; its program name is then that file's basename, and its header names the generator
152
+ # @param legacy [Array<String>, nil] verbs an executable hands to `Hecks::CLI` first
153
+ # @param opted [Boolean] whether the chapter's world declares a `launcher` setting
154
+ # @return [String] the Ruby source
155
+ # @raise [ArgumentError] if a name, path, executable or legacy verb is not plain
156
+ def launcher(path, name, program, executable: nil, legacy: nil, opted: !executable.nil?)
157
+ plain!("chapter name", name, NAME)
158
+ plain!("domain path", path, PATH)
90
159
  snake = Naming.snake(name)
91
- up = "../" * path.count("/").succ
160
+ if executable
161
+ plain!("launcher executable", executable, PATH)
162
+ if executable.split("/").include?("..")
163
+ raise ArgumentError, "launcher executable #{executable.inspect} must stay inside the root"
164
+ end
165
+
166
+ up = "../" * File.dirname(executable).split("/").reject { |part| part == "." }.length
167
+ boot = %(File.expand_path("#{up}#{path}", __dir__))
168
+ program = GENERATOR
169
+ where = executable
170
+ shown = File.basename(executable)
171
+ else
172
+ up = "../" * path.count("/").succ
173
+ boot = "__dir__"
174
+ where = shown = "#{path}/#{snake}"
175
+ end
176
+
177
+ handoff = legacy_handoff(Array(legacy)) if executable
178
+ encoding = opted ? ENCODING : ""
179
+ ending = opted ? OPTED_ENDING : PLAIN_ENDING
92
180
 
93
181
  <<~RUBY
94
182
  #!/usr/bin/env ruby
@@ -99,23 +187,94 @@ module Hecks
99
187
  # projected from the bluebook beside it every time this runs, so a change
100
188
  # to the chapter shows up here without re-minting anything.
101
189
  #
102
- # #{path}/#{snake} every verb, and every question
103
- # #{path}/#{snake} <verb> --help what it wants, and how it refuses
104
-
105
- $LOAD_PATH.unshift File.expand_path("#{up}lib", __dir__)
190
+ # #{where} every verb, and every question
191
+ # #{where} <verb> --help what it wants, and how it refuses
106
192
 
193
+ #{encoding}$LOAD_PATH.unshift File.expand_path("#{up}lib", __dir__)
194
+ #{handoff}
107
195
  require "hecks"
108
196
 
197
+ #{entry(name, boot, shown, opted)}
198
+ #{ending}
199
+ RUBY
200
+ end
201
+
202
+ # @api private
203
+ # @return [String] the launcher's middle: for an opted-in launcher, usage answered from the
204
+ # projection and a boot only for a line that runs a verb; for any other, the boot and
205
+ # dispatch every launcher has always had, byte for byte
206
+ def entry(name, boot, shown, opted)
207
+ opted ? described_entry(name, boot, shown) : plain_entry(name, boot, shown)
208
+ end
209
+
210
+ # @api private
211
+ # @return [String] the opted-in launcher's middle
212
+ def described_entry(name, boot, shown)
213
+ <<~RUBY.chomp
214
+ # Usage is answered from the projected chapter alone: no adapter is bound and no
215
+ # database is opened. Only a line that runs a verb boots the domain.
216
+ domain = #{boot}
217
+ program = "#{shown}"
218
+ described = begin
219
+ Hecks.describe(domain)
220
+ rescue StandardError => e
221
+ abort "cannot open #{name}: \#{e.message.lines.first.strip}"
222
+ end
223
+
224
+ text, status, reason = Hecks::Doors::CliRunner.usage(
225
+ runtime: described, argv: ARGV, program: program
226
+ )
227
+ unless text
228
+ runtime = begin
229
+ Hecks.boot(domain, install_doors: false)
230
+ rescue StandardError => e
231
+ abort "cannot open #{name}: \#{e.message.lines.first.strip}"
232
+ end
233
+ text, status, reason = Hecks::Doors::CliRunner.call(
234
+ runtime: runtime, argv: ARGV, program: program
235
+ )
236
+ end
237
+ RUBY
238
+ end
239
+
240
+ # @api private
241
+ # @return [String] the middle every launcher had before opted-in ones answered usage alone
242
+ def plain_entry(name, boot, shown)
243
+ <<~RUBY.chomp
109
244
  runtime = begin
110
- Hecks.boot(__dir__, install_facade: false)
245
+ Hecks.boot(#{boot}, install_doors: false)
111
246
  rescue StandardError => e
112
247
  abort "cannot open #{name}: \#{e.message.lines.first.strip}"
113
248
  end
114
249
 
115
- text, status = Hecks::Facade::CliRunner.call(
116
- runtime: runtime, argv: ARGV, program: "#{path}/#{snake}"
250
+ text, status = Hecks::Doors::CliRunner.call(
251
+ runtime: runtime, argv: ARGV, program: "#{shown}"
117
252
  )
118
- status.zero? ? puts(text) : abort(text)
253
+ RUBY
254
+ end
255
+
256
+ # @api private
257
+ def plain!(what, value, pattern)
258
+ return if value.to_s.match?(pattern)
259
+
260
+ raise ArgumentError, "#{what} #{value.to_s.inspect} is not a plain word or path"
261
+ end
262
+
263
+ # @api private
264
+ # @return [String] the lines that hand the legacy verbs to `Hecks::CLI`, or nothing
265
+ def legacy_handoff(legacy)
266
+ return "" if legacy.empty?
267
+
268
+ legacy.each { |verb| plain!("legacy verb", verb, VERB) }
269
+
270
+ <<~RUBY
271
+
272
+ # The names the gem has always shipped keep their positional forms.
273
+ LEGACY = %w[#{legacy.join(' ')}].freeze
274
+ if LEGACY.include?(ARGV.first)
275
+ require "hecks/cli"
276
+ exit Hecks::CLI.start(ARGV) unless Hecks::CLI.launcher_form?(ARGV)
277
+ end
119
278
  RUBY
120
279
  end
121
280
  end
@@ -2,27 +2,21 @@ require_relative "../../hecks"
2
2
 
3
3
  module Hecks
4
4
  module CLI
5
- # The command behind `bin/project_diagrams` and `hecks project_diagrams`: boots a
5
+ # The command behind `hecks project_diagrams`: boots a
6
6
  # domain, finds the chapter it names, and writes its Mermaid diagrams
7
7
  # (`Projections::Diagrams`) under `docs/generated/diagrams/<chapter>/` below the
8
- # root.
8
+ # root. Only this positional form writes; the launcher's `domain=… chapter=…` question
9
+ # prints the same files' text and writes nothing.
9
10
  module ProjectDiagrams
10
11
  module_function
11
12
 
12
- # Projects and writes one chapter's diagrams, then lists what was written.
13
- #
14
- # @param argv [Array<String>] the domain path, then the chapter name
15
- # @param program [String] the name the usage message calls this command by
16
- # @param root [String] the directory `docs/generated/diagrams/` is written under
17
- # @return [void]
18
- # @raise [SystemExit] when either argument is missing
19
13
  def call(argv, program:, root:)
20
14
  usage = "usage: #{program} <domain-path> <ChapterName>"
21
15
  domain_path = argv[0] or abort usage
22
16
  chapter_name = argv[1] or abort usage
23
17
 
24
18
  runtime = Hecks.boot(File.expand_path(domain_path, Dir.pwd))
25
- chapter = runtime.registry.bluebook(chapter_name)
19
+ chapter = runtime.registry.bluebook(chapter_name) or abort "no chapter named #{chapter_name}"
26
20
  hecksagon = runtime.registry.hecksagon(chapter_name)
27
21
  directory = File.expand_path("docs/generated/diagrams/#{Naming.snake(chapter_name)}", root)
28
22
 
@@ -0,0 +1,44 @@
1
+ require_relative "../../hecks"
2
+
3
+ module Hecks
4
+ module CLI
5
+ # The command behind `hecks glossary`: boots a domain and projects one chapter into its
6
+ # Ubiquitous Language glossary, `glossary.md` plus `html/index.html` rendered from it, in the
7
+ # domain's own `glossary/` folder.
8
+ #
9
+ # A field the deployment marks sensitive (`has_phi(readable_by:)` in the domain's `.hecksagon`)
10
+ # is tagged in the glossary with its category. spec/glossary_spec.rb re-projects every one and
11
+ # refuses a diff, so a committed glossary never lags the bluebook it describes.
12
+ module ProjectGlossary
13
+ module_function
14
+
15
+ # Writes the chapter's glossary and prints each file written.
16
+ #
17
+ # @param argv [Array<String>] the domain path, then the chapter's name
18
+ # @param program [String] the name the usage line shows
19
+ # @return [void]
20
+ # @raise [SystemExit] with the usage line when an argument is missing
21
+ def call(argv, program: "hecks glossary")
22
+ usage = "usage: #{program} <domain-path> <ChapterName>"
23
+ domain_path = argv[0] or abort usage
24
+ chapter_name = argv[1] or abort usage
25
+
26
+ domain = File.expand_path(domain_path, Dir.pwd)
27
+ runtime = Hecks.boot(domain)
28
+ chapter = runtime.registry.bluebook(chapter_name)
29
+
30
+ markings = runtime.registry.pending_privacy_markings.select do |marking|
31
+ marking[:domain].to_s.start_with?("#{chapter_name}::")
32
+ end
33
+
34
+ written = Projector.write(
35
+ Projector.call(:glossary, bluebook: chapter, options: { markings: markings }),
36
+ File.join(domain, "glossary"), as: :files
37
+ )
38
+
39
+ puts "wrote #{written.size} file(s):"
40
+ written.each { |path| puts " #{path}" }
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../../hecks"
4
+ require_relative "../projection_files"
5
+
6
+ module Hecks
7
+ module CLI
8
+ # The command behind `hecks project_reference`: regenerates `docs/implemented/reference/` from
9
+ # the language's Syntax chapter. Tables come from the declaration; prose is kept from the
10
+ # committed pages.
11
+ module Reference
12
+ module_function
13
+
14
+ # Writes the pages and reports both coverage gates together (`DocCoverage` asks the same
15
+ # as an exit status).
16
+ #
17
+ # @param root [String] the repository root
18
+ # @param out [IO] where the report goes
19
+ # @return [Integer] the exit status, always 0
20
+ def call(root:, out: $stdout)
21
+ directory = File.join(root, "docs/implemented/reference")
22
+ written = Hecks::ProjectionFiles.write(:reference, root: root)
23
+ out.puts "wrote #{written.size - 1} pages to docs/implemented/reference/, " \
24
+ "and regenerated README.md's own indexes"
25
+ { "prose" => Hecks::Doc::Reference.undocumented(directory),
26
+ "a running example" => Hecks::Doc::Reference.unexemplified(directory) }.each do |owed, missing|
27
+ report(out, owed, missing)
28
+ end
29
+ 0
30
+ end
31
+
32
+ # @param out [IO] where the line goes
33
+ # @param owed [String] what each word owes: prose, or a running example
34
+ # @param missing [Array<String>] the words that lack it
35
+ # @return [void]
36
+ def report(out, owed, missing)
37
+ if missing.empty?
38
+ out.puts "every live word carries #{owed}."
39
+ else
40
+ out.puts "#{missing.size} word(s) still carry no #{owed}:"
41
+ missing.each { |word| out.puts " #{word}" }
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,44 @@
1
+ require_relative "../../hecks"
2
+
3
+ module Hecks
4
+ module CLI
5
+ # The logic behind `hecks refresh_projections` and Custodian's `Operation.RefreshProjections`:
6
+ # forces every
7
+ # read-model projection a booted domain declares to catch up now, the same catch-up a boot
8
+ # runs lazily on first read.
9
+ module RefreshProjections
10
+ module_function
11
+
12
+ # Boots the domain `argv` names and refreshes its projections, as `hecks refresh_projections`
13
+ # does.
14
+ #
15
+ # @param argv [Array<String>] the domain directory, first
16
+ # @param program [String] the name the usage message calls this command by
17
+ # @return [Integer] 0
18
+ # @raise [SystemExit] when `argv` is empty
19
+ def run(argv, program: "hecks refresh_projections")
20
+ domain = argv.first or abort "usage: #{program} <domain>"
21
+ call(Hecks.boot(domain))
22
+ 0
23
+ end
24
+
25
+ # Refreshes every projection of every chapter in a booted runtime.
26
+ #
27
+ # @param runtime [Runtime] a booted domain
28
+ # @return [Integer] how many projections were caught up
29
+ def call(runtime)
30
+ refreshed = 0
31
+ runtime.registry.bluebooks.each do |domain, bluebook|
32
+ bluebook.aggregates.each do |aggregate|
33
+ worker = Ports::Projection.worker(runtime.registry, domain, aggregate, policy: :refresh)
34
+ next unless worker
35
+
36
+ worker.catch_up!
37
+ refreshed += 1
38
+ end
39
+ end
40
+ refreshed
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,150 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "json"
5
+ require "open3"
6
+ require "yaml"
7
+
8
+ module Hecks
9
+ module CLI
10
+ # The command behind `hecks refresh_runtime_baseline`: regenerates the committed runtime
11
+ # baselines the sharded CI jobs group from. It prefers one CI run's timings; a local run is
12
+ # the fallback.
13
+ #
14
+ # hecks refresh_runtime_baseline --from-run <run-id> # preferred: one CI run's timings
15
+ # hecks refresh_runtime_baseline [workers] # fallback: this machine only
16
+ #
17
+ # `--from-run` reads the runtime-log artifacts of a successful run and writes a family only
18
+ # when every leg uploaded one; a partial set would skew the split. Runner seconds differ from a
19
+ # laptop's, so a local baseline misses subprocess-heavy specs. The local mode refuses a red run.
20
+ module RefreshRspecRuntimeBaseline
21
+ REPO = "heckslabs/hecks"
22
+ USAGE = "usage: hecks refresh_runtime_baseline --from-run <run-id> | [workers]"
23
+
24
+ # Only `spec/..._spec.rb:<seconds>` lines; RSpec's "Run options" line must not be copied
25
+ # into a committed file. Seconds can arrive in exponent form (`9.69e-05`).
26
+ RUNTIME_LINE = %r{\A(?<file>spec/\S+_spec\.rb):(?<seconds>\d+(?:\.\d+)?(?:e-?\d+)?)\z}
27
+
28
+ module_function
29
+
30
+ # Refreshes the baselines from a CI run or a local run.
31
+ #
32
+ # @param argv [Array<String>] `--from-run RUN_ID`, or optionally the local worker count
33
+ # @param root [String] the checkout whose `.github/` baselines are rewritten
34
+ # @param out [IO] where what was written goes
35
+ # @return [Integer] the exit status, 0 once written
36
+ # @raise [SystemExit] when the run is unreadable or unsuccessful, the local suite is red, or
37
+ # no artifact family is complete
38
+ def call(argv, root:, out: $stdout)
39
+ if argv.first == "--from-run"
40
+ from_run(root, argv.fetch(1) { abort USAGE }, out)
41
+ else
42
+ from_local(root, argv.fetch(0, "6"), out)
43
+ end
44
+ 0
45
+ end
46
+
47
+ # Reads the leg counts from the workflow matrix so a resize cannot leave a stale count here.
48
+ #
49
+ # @param root [String] the checkout
50
+ # @return [Hash{String => Hash}] each artifact family's leg count and baseline file
51
+ def families(root)
52
+ {
53
+ "rspec-runtime-group" => { legs: matrix_legs(root, "ci-rspec.yml", "rspec_shard"),
54
+ baseline: ".github/rspec_runtime_baseline.log" },
55
+ "postgres-io-runtime-group" => { legs: matrix_legs(root, "ci-postgres-io-parallel.yml",
56
+ "rspec_postgres_io_parallel_shard"),
57
+ baseline: ".github/postgres_io_runtime_baseline.log" }
58
+ }
59
+ end
60
+
61
+ # @param root [String] the checkout
62
+ # @param workflow [String] the workflow file's name
63
+ # @param job [String] the job whose matrix is counted
64
+ # @return [Integer] how many groups the job's matrix has
65
+ def matrix_legs(root, workflow, job)
66
+ YAML.load_file(File.join(root, ".github/workflows", workflow)).dig("jobs", job, "strategy", "matrix", "group").size
67
+ end
68
+
69
+ # @param paths [Array<String>] runtime logs
70
+ # @return [Array<String>] one sorted `file:seconds` line per spec file
71
+ def baseline_lines(paths)
72
+ seconds_by_file = paths.flat_map { |path| File.readlines(path) }.filter_map do |line|
73
+ match = RUNTIME_LINE.match(line.strip) or next
74
+ [match[:file], Float(match[:seconds])]
75
+ end.to_h
76
+ seconds_by_file.map { |file, seconds| format("%<file>s:%<seconds>.2f", file: file, seconds: seconds) }.sort
77
+ end
78
+
79
+ # @param root [String] the checkout
80
+ # @param relative [String] the baseline's path under the checkout
81
+ # @param lines [Array<String>] the baseline's lines
82
+ # @param out [IO] where the note goes
83
+ # @return [void]
84
+ def write_baseline(root, relative, lines, out)
85
+ File.write(File.join(root, relative), "#{lines.join("\n")}\n")
86
+ out.puts "wrote #{relative}: #{lines.size} spec files"
87
+ end
88
+
89
+ # @param run_id [String] the CI run's id
90
+ # @return [void]
91
+ # @raise [SystemExit] when `gh` cannot read the run or it did not succeed
92
+ def refuse_unless_successful!(run_id)
93
+ out, status = Open3.capture2("gh", "run", "view", run_id, "-R", REPO, "--json", "conclusion")
94
+ abort "hecks refresh_runtime_baseline: could not read run #{run_id}" unless status.success?
95
+
96
+ conclusion = JSON.parse(out)["conclusion"]
97
+ return if conclusion == "success"
98
+
99
+ abort "hecks refresh_runtime_baseline: run #{run_id} concluded #{conclusion.inspect} — " \
100
+ "refusing to write a baseline from anything but a successful run"
101
+ end
102
+
103
+ # @param root [String] the checkout
104
+ # @param run_id [String] the CI run's id
105
+ # @param out [IO] where what was written goes
106
+ # @return [void]
107
+ # @raise [SystemExit] when no family of artifacts is complete
108
+ def from_run(root, run_id, out)
109
+ refuse_unless_successful!(run_id)
110
+ dir = File.join(root, "tmp/ci-runtime-#{run_id}")
111
+ FileUtils.rm_rf(dir)
112
+
113
+ written = families(root).count do |prefix, family|
114
+ system("gh", "run", "download", run_id, "-R", REPO, "-p", "#{prefix}-*", "-D", dir,
115
+ out: File::NULL, err: File::NULL)
116
+ logs = Dir[File.join(dir, "#{prefix}-*", "*.log")]
117
+ legs = logs.map { |path| File.basename(File.dirname(path)) }.uniq.size
118
+ if legs == family[:legs]
119
+ write_baseline(root, family[:baseline], baseline_lines(logs), out)
120
+ true
121
+ else
122
+ warn "skipping #{family[:baseline]}: run #{run_id} has #{legs} of #{family[:legs]} #{prefix}-* artifacts"
123
+ false
124
+ end
125
+ end
126
+ return unless written.zero?
127
+
128
+ abort "hecks refresh_runtime_baseline: run #{run_id} had no complete artifact family — nothing written"
129
+ end
130
+
131
+ # @param root [String] the checkout
132
+ # @param workers [String] how many `parallel_rspec` workers to time with
133
+ # @param out [IO] where what was written goes
134
+ # @return [void]
135
+ # @raise [SystemExit] when the local suite is red
136
+ def from_local(root, workers, out)
137
+ raw = "tmp/rspec_runtime_baseline.raw.log"
138
+ FileUtils.mkdir_p(File.join(root, "tmp"))
139
+ FileUtils.rm_f(File.join(root, raw))
140
+
141
+ formatters = "--tag ~io --tag ~fuzzing --format progress --format ParallelTests::RSpec::RuntimeLogger --out #{raw}"
142
+ green = system("bundle", "exec", "parallel_rspec", "spec", "-n", workers, "-o", formatters, chdir: root)
143
+ abort "hecks refresh_runtime_baseline: the spec run failed — not writing a baseline from a red suite" unless green
144
+
145
+ write_baseline(root, families(root).fetch("rspec-runtime-group")[:baseline],
146
+ baseline_lines([File.join(root, raw)]), out)
147
+ end
148
+ end
149
+ end
150
+ end