hecks 2.6.0 → 2.8.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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +13 -0
  3. data/lib/hecks/adapters/driven/google_authentication.rb +1 -1
  4. data/lib/hecks/adapters/driven/lambda/client.rb +1 -1
  5. data/lib/hecks/adapters/driven/memory.rb +1 -1
  6. data/lib/hecks/adapters/driven/postgres.rb +1 -1
  7. data/lib/hecks/adapters/driven/prism.rb +2 -2
  8. data/lib/hecks/adapters/driven/sqlite/projection.rb +1 -1
  9. data/lib/hecks/adapters/driven/tenant_provisioner.rb +31 -10
  10. data/lib/hecks/behaviors/expectations.rb +2 -2
  11. data/lib/hecks/bluebook/assembly/contract.rb +1 -1
  12. data/lib/hecks/bluebook/assembly/contracts.rb +5 -5
  13. data/lib/hecks/bluebook/assembly/specializer.rb +2 -2
  14. data/lib/hecks/bluebook/assembly.rb +1 -1
  15. data/lib/hecks/bluebook/behaviour/chapter.rb +5 -2
  16. data/lib/hecks/bluebook/behaviour/read_model.rb +18 -0
  17. data/lib/hecks/bluebook/capabilities.rb +2 -2
  18. data/lib/hecks/bluebook/chapter.rb +1 -1
  19. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +2 -2
  20. data/lib/hecks/bluebook/dsl/binding_proxy.rb +6 -1
  21. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +2 -2
  22. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +2 -0
  23. data/lib/hecks/bluebook/dsl/command_builder.rb +3 -3
  24. data/lib/hecks/bluebook/dsl/entity_builder.rb +1 -1
  25. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +1 -1
  26. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +14 -9
  27. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +1 -1
  28. data/lib/hecks/bluebook/dsl/rule_reference.rb +3 -3
  29. data/lib/hecks/bluebook/dsl/translation_builder.rb +1 -1
  30. data/lib/hecks/bluebook/dsl/world_builder.rb +47 -3
  31. data/lib/hecks/bluebook/hexagon.rb +15 -7
  32. data/lib/hecks/bluebook/meta_validator/judge.rb +3 -3
  33. data/lib/hecks/bluebook/meta_validator/plan.rb +4 -4
  34. data/lib/hecks/bluebook/meta_validator/readings.rb +1 -1
  35. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +2 -2
  36. data/lib/hecks/bluebook/meta_validator/shapes.rb +1 -1
  37. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +11 -10
  38. data/lib/hecks/bluebook/meta_validator/world_judge.rb +3 -1
  39. data/lib/hecks/bluebook/meta_validator.rb +1 -1
  40. data/lib/hecks/bluebook/model_check/client_profile.rb +4 -70
  41. data/lib/hecks/bluebook/model_check.rb +13 -14
  42. data/lib/hecks/cache_dir.rb +103 -0
  43. data/lib/hecks/cli/document.rb +104 -0
  44. data/lib/hecks/cli/ir.rb +47 -0
  45. data/lib/hecks/cli/mcp.rb +32 -0
  46. data/lib/hecks/cli/mcp_door.rb +461 -0
  47. data/lib/hecks/cli/model_check.rb +270 -0
  48. data/lib/hecks/cli/project_cli.rb +123 -0
  49. data/lib/hecks/cli/project_diagrams.rb +43 -0
  50. data/lib/hecks/cli/run.rb +219 -0
  51. data/lib/hecks/cli/smoke_test.rb +59 -0
  52. data/lib/hecks/cli/stores.rb +54 -0
  53. data/lib/hecks/cli.rb +166 -0
  54. data/lib/hecks/embryonaut_bluebook/lock.rb +72 -0
  55. data/lib/hecks/embryonaut_bluebook/shape.rb +47 -0
  56. data/lib/hecks/embryonaut_bluebook/vendor.rb +194 -0
  57. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +88 -0
  58. data/lib/hecks/embryonaut_bluebook.rb +29 -3
  59. data/lib/hecks/facade/handle.rb +2 -2
  60. data/lib/hecks/facade/surface/aggregate_door.rb +1 -1
  61. data/lib/hecks/forms/value_object_shape.rb +1 -1
  62. data/lib/hecks/framework/bluebook/console_settings.bluebook +3 -3
  63. data/lib/hecks/language/bluebook/vocabulary.bluebook +16 -0
  64. data/lib/hecks/language/world/world.bluebook +32 -2
  65. data/lib/hecks/mcp_door_scope.rb +176 -0
  66. data/lib/hecks/ports/key_vault.rb +1 -1
  67. data/lib/hecks/ports/persistence/append_only.rb +1 -1
  68. data/lib/hecks/ports/persistence/binding_policy.rb +16 -5
  69. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +3 -2
  70. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +2 -2
  71. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +2 -2
  72. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +132 -0
  73. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +1 -1
  74. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +2 -2
  75. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +1 -1
  76. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +1 -1
  77. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +13 -7
  78. data/lib/hecks/ports/persistence/plugins/era.rb +7 -4
  79. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +73 -0
  80. data/lib/hecks/ports/persistence/postgres_dump.rb +125 -0
  81. data/lib/hecks/ports/persistence/repository_factory.rb +2 -2
  82. data/lib/hecks/ports/persistence/state_codec.rb +1 -1
  83. data/lib/hecks/ports/persistence.rb +4 -0
  84. data/lib/hecks/projections/deploy/fargate/assembly.rb +193 -0
  85. data/lib/hecks/projections/deploy/fargate/cdn.rb +318 -0
  86. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +87 -0
  87. data/lib/hecks/projections/deploy/fargate/check.rb +172 -0
  88. data/lib/hecks/projections/deploy/fargate/containers.rb +412 -0
  89. data/lib/hecks/projections/deploy/fargate/extras.rb +268 -0
  90. data/lib/hecks/projections/deploy/fargate/monitoring.rb +448 -0
  91. data/lib/hecks/projections/deploy/fargate/settings.rb +235 -0
  92. data/lib/hecks/projections/deploy/fargate/yaml.rb +116 -0
  93. data/lib/hecks/projections/deploy/fargate.rb +188 -139
  94. data/lib/hecks/projections/deploy/lambda.rb +8 -8
  95. data/lib/hecks/projections/deploy/preview/access_yaml.rb +145 -0
  96. data/lib/hecks/projections/deploy/preview/containers.rb +218 -0
  97. data/lib/hecks/projections/deploy/preview/preview.sh.erb +446 -0
  98. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +216 -0
  99. data/lib/hecks/projections/deploy/preview/script.rb +40 -0
  100. data/lib/hecks/projections/deploy/preview/settings.rb +140 -0
  101. data/lib/hecks/projections/deploy/preview/task_yaml.rb +215 -0
  102. data/lib/hecks/projections/deploy/preview/template.rb +247 -0
  103. data/lib/hecks/projections/deploy/preview/yaml_text.rb +48 -0
  104. data/lib/hecks/projections/deploy/preview.rb +103 -0
  105. data/lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl +182 -0
  106. data/lib/hecks/projections/deploy/scripts/expected-era.header +17 -0
  107. data/lib/hecks/projections/deploy/scripts/hosting.mk.tmpl +54 -0
  108. data/lib/hecks/projections/deploy/scripts/settings.rb +114 -0
  109. data/lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl +232 -0
  110. data/lib/hecks/projections/deploy/scripts.rb +171 -0
  111. data/lib/hecks/projections/deploy/smoke/harness.js +366 -0
  112. data/lib/hecks/projections/deploy/smoke/workflow.yml.tmpl +56 -0
  113. data/lib/hecks/projections/deploy/smoke.rb +159 -0
  114. data/lib/hecks/projections/deploy/template_diff/comparer.rb +231 -0
  115. data/lib/hecks/projections/deploy/template_diff/loader.rb +105 -0
  116. data/lib/hecks/projections/deploy/template_diff.rb +173 -0
  117. data/lib/hecks/projections/glossary/sensitivity.rb +1 -1
  118. data/lib/hecks/projections/reference.rb +7 -1
  119. data/lib/hecks/projections.rb +2 -0
  120. data/lib/hecks/projector/exporter.rb +4 -4
  121. data/lib/hecks/projector/target.rb +1 -1
  122. data/lib/hecks/release/gem_pin/published_versions.rb +58 -0
  123. data/lib/hecks/release/gem_pin.rb +112 -0
  124. data/lib/hecks/release/runner/ci_publisher.rb +96 -0
  125. data/lib/hecks/release/runner/commands.rb +68 -0
  126. data/lib/hecks/release/runner/console.rb +52 -0
  127. data/lib/hecks/release/runner/gem_publisher.rb +44 -0
  128. data/lib/hecks/release/runner/git.rb +48 -0
  129. data/lib/hecks/release/runner/npm_publisher.rb +89 -0
  130. data/lib/hecks/release/runner/preflight.rb +119 -0
  131. data/lib/hecks/release/runner/published.rb +55 -0
  132. data/lib/hecks/release/runner/tagger.rb +87 -0
  133. data/lib/hecks/release/runner.rb +244 -0
  134. data/lib/hecks/router/namespace_installer.rb +1 -1
  135. data/lib/hecks/runtime/command_interpreter.rb +3 -3
  136. data/lib/hecks/runtime/command_rules/admissibility.rb +2 -2
  137. data/lib/hecks/runtime/command_rules/arithmetic.rb +2 -2
  138. data/lib/hecks/runtime/entity_element.rb +1 -1
  139. data/lib/hecks/runtime/entity_interpreter.rb +1 -1
  140. data/lib/hecks/runtime/invocation.rb +1 -1
  141. data/lib/hecks/runtime/loader.rb +27 -3
  142. data/lib/hecks/runtime/outbox.rb +1 -1
  143. data/lib/hecks/runtime/reaction_invocation.rb +3 -3
  144. data/lib/hecks/runtime/read_model_interpreter.rb +37 -15
  145. data/lib/hecks/runtime/reference_hop.rb +4 -4
  146. data/lib/hecks/runtime/registry/saga_persistence.rb +8 -2
  147. data/lib/hecks/runtime/registry/verification.rb +15 -13
  148. data/lib/hecks/runtime/registry/world_defaults.rb +106 -0
  149. data/lib/hecks/runtime/registry.rb +22 -13
  150. data/lib/hecks/runtime/saga_interpreter.rb +1 -1
  151. data/lib/hecks/runtime/tenant_check.rb +1 -1
  152. data/lib/hecks/runtime/value/coercion.rb +3 -3
  153. data/lib/hecks/runtime/value/entity_list_coercion.rb +1 -1
  154. data/lib/hecks/storehouse.rb +18 -12
  155. data/lib/hecks/vendoring/git_environment.rb +35 -0
  156. data/lib/hecks/vendoring/git_source.rb +102 -0
  157. data/lib/hecks/vendoring.rb +102 -0
  158. data/lib/hecks/version.rb +1 -1
  159. data/lib/hecks/vocabulary.rb +5 -0
  160. data/lib/hecks.rb +8 -2
  161. metadata +72 -58
  162. data/lib/hecks/bench/cli.rb +0 -74
  163. data/lib/hecks/bench/environment.rb +0 -100
  164. data/lib/hecks/bench/postgres_probe.rb +0 -41
  165. data/lib/hecks/bench/report.rb +0 -116
  166. data/lib/hecks/bench/ruby_runner.rb +0 -151
  167. data/lib/hecks/bench/run.rb +0 -55
  168. data/lib/hecks/bench/rust_runner.rb +0 -165
  169. data/lib/hecks/bench/stats.rb +0 -75
  170. data/lib/hecks/bench/suite.rb +0 -172
  171. data/lib/hecks/bench/workload.rb +0 -137
  172. data/lib/hecks/bench.rb +0 -28
  173. data/lib/hecks/codemod.rb +0 -443
  174. data/lib/hecks/corpus.rb +0 -479
  175. data/lib/hecks/doc/reference.rb +0 -585
  176. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
  177. data/lib/hecks/fuzzing/combination_miner.rb +0 -178
  178. data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
  179. data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
  180. data/lib/hecks/fuzzing/differential.rb +0 -192
  181. data/lib/hecks/fuzzing/domain_generator.rb +0 -871
  182. data/lib/hecks/fuzzing/era_boundary.rb +0 -154
  183. data/lib/hecks/fuzzing/form_census.rb +0 -285
  184. data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
  185. data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
  186. data/lib/hecks/fuzzing/isolated_boot.rb +0 -604
  187. data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
  188. data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
  189. data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
  190. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
  191. data/lib/hecks/fuzzing/properties/guards.rb +0 -398
  192. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
  193. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
  194. data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
  195. data/lib/hecks/fuzzing/properties/querying.rb +0 -260
  196. data/lib/hecks/fuzzing/properties.rb +0 -267
  197. data/lib/hecks/fuzzing/qa_settings.rb +0 -164
  198. data/lib/hecks/fuzzing/replay.rb +0 -930
  199. data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
  200. data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
  201. data/lib/hecks/fuzzing/self_consistency.rb +0 -825
  202. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
  203. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
  204. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
  205. data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
  206. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
  207. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
  208. data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
  209. data/lib/hecks/fuzzing/shrinker.rb +0 -309
  210. data/lib/hecks/fuzzing/structural_skips.rb +0 -53
  211. data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
  212. data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
  213. data/lib/hecks/fuzzing/value_generator.rb +0 -340
  214. data/lib/hecks/fuzzing.rb +0 -23
  215. data/lib/hecks/grammar/evolve.rb +0 -524
  216. data/lib/hecks/query_ir.rb +0 -482
@@ -0,0 +1,102 @@
1
+ require "fileutils"
2
+ require "tmpdir"
3
+ require_relative "vendoring/git_environment"
4
+ require_relative "vendoring/git_source"
5
+
6
+ module Hecks
7
+ # Pins an exact commit of one directory of another repository into a
8
+ # project's own tree.
9
+ #
10
+ # ## What it is
11
+ #
12
+ # A project that consumes a package from a private repository cannot clone
13
+ # that repository when its image builds, and a live pull would make the build
14
+ # depend on whatever is checked out. So the files are exported from one
15
+ # commit, committed into the consumer, and a marker file beside them records
16
+ # which commit they came from. Only the files directly inside the named
17
+ # subtree are taken; the source's own specs, ports, adapters and data stay
18
+ # where they are.
19
+ #
20
+ # ## Marker
21
+ #
22
+ # `VENDORED_COMMIT` holds the full 40-character commit id and a newline, so
23
+ # `git -C <source> show <id>:<subtree>` reproduces the vendored files. The
24
+ # marker sits in `into`, beside the exported directory.
25
+ #
26
+ # ## Whole-directory replacement
27
+ #
28
+ # A pin replaces `into` entirely, so a file the source dropped does not
29
+ # linger. Nothing is touched until the export succeeded and the optional
30
+ # block accepted it.
31
+ module Vendoring
32
+ # Raised when a pin cannot be made or is refused.
33
+ class Error < StandardError; end
34
+
35
+ # File name of the commit marker written into every pinned directory.
36
+ MARKER = "VENDORED_COMMIT".freeze
37
+
38
+ # What a pin produced.
39
+ #
40
+ # @!attribute [r] commit
41
+ # @return [String] the full commit id the files were exported from
42
+ # @!attribute [r] dir
43
+ # @return [String] the directory holding the exported subtree
44
+ # @!attribute [r] files
45
+ # @return [Array<String>] the exported files' names, sorted
46
+ Pin = Struct.new(:commit, :dir, :files, keyword_init: true)
47
+
48
+ # Exports the top-level files of one directory at one commit into `into`.
49
+ #
50
+ # The exported files land in `into/<last segment of subtree>/`; the marker
51
+ # lands in `into` itself. The optional block sees the staged files before
52
+ # anything is replaced and may raise to refuse the pin.
53
+ #
54
+ # @param from [String] path of the local source repository
55
+ # @param ref [String] the commit-ish to export (branch, tag or commit id)
56
+ # @param subtree [String] repository-relative directory to export, such as
57
+ # `"payments/bluebook"`
58
+ # @param into [String] the directory to replace with the export
59
+ # @param glob [String] `File.fnmatch` pattern each exported file's name must match
60
+ # @param marker [String] name of the file recording the commit
61
+ # @yield [staged, commit] the staged files, before `into` is touched
62
+ # @yieldparam staged [String] directory holding the exported files
63
+ # @yieldparam commit [String] the resolved commit id
64
+ # @yieldreturn [Hash{String => String}, nil] extra files to write into `into`,
65
+ # keyed by file name; nil for none
66
+ # @return [Pin] the commit and where the files landed
67
+ # @raise [Vendoring::Error] if the source is missing, `ref` names no commit,
68
+ # the subtree holds no matching file, or the block refuses
69
+ def self.pin(from:, ref:, subtree:, into:, glob: "*", marker: MARKER)
70
+ source = GitSource.new(from)
71
+ commit = source.commit(ref)
72
+ files = source.files(commit, subtree, glob)
73
+ raise Error, "no #{glob} files in #{subtree} at #{ref} in #{source.path}" if files.empty?
74
+
75
+ Dir.mktmpdir("hecks-vendoring") do |stage|
76
+ source.export(commit, files, stage)
77
+ staged = File.join(stage, subtree)
78
+ extras = block_given? ? yield(staged, commit) : nil
79
+ install(staged, into, marker, commit, extras || {})
80
+ Pin.new(commit: commit, dir: File.join(into, File.basename(subtree)),
81
+ files: files.map { |file| File.basename(file) })
82
+ end
83
+ end
84
+
85
+ # Replaces `into` with the staged files, the marker and any extras.
86
+ #
87
+ # @param staged [String] directory holding the exported files
88
+ # @param into [String] the directory to replace
89
+ # @param marker [String] marker file name
90
+ # @param commit [String] commit id the marker records
91
+ # @param extras [Hash{String => String}] more files to write into `into`
92
+ # @return [void]
93
+ def self.install(staged, into, marker, commit, extras)
94
+ FileUtils.rm_rf(into)
95
+ FileUtils.mkdir_p(into)
96
+ FileUtils.cp_r(staged, File.join(into, File.basename(staged)))
97
+ File.write(File.join(into, marker), "#{commit}\n")
98
+ extras.each { |name, text| File.write(File.join(into, name), text) }
99
+ end
100
+ private_class_method :install
101
+ end
102
+ end
data/lib/hecks/version.rb CHANGED
@@ -12,5 +12,5 @@ module Hecks
12
12
  # it there, or even in the consuming Gemfile, never closed the gap,
13
13
  # because gemspec evaluation happens before anything Bundler
14
14
  # resolves is actually loadable yet.
15
- VERSION = "2.6.0".freeze
15
+ VERSION = "2.8.0".freeze
16
16
  end
@@ -254,6 +254,10 @@ module Hecks
254
254
  {"refusal"=>"InvariantViolation", "site"=>"admits_declared_set", "argument"=>"offered", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
255
255
  {"refusal"=>"InvariantViolation", "site"=>"undeclared_set", "argument"=>"name", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
256
256
  {"refusal"=>"InvariantViolation", "site"=>"undeclared_set", "argument"=>"admits", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
257
+ {"refusal"=>"InvariantViolation", "site"=>"group_by_collision", "argument"=>"read_model", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
258
+ {"refusal"=>"InvariantViolation", "site"=>"group_by_collision", "argument"=>"fields", "shape"=>"list", "quoting"=>"none", "separator"=>", ", "sorted"=>"false", "when_empty"=>""}.freeze,
259
+ {"refusal"=>"InvariantViolation", "site"=>"group_by_collision", "argument"=>"ids", "shape"=>"list", "quoting"=>"inspect", "separator"=>", ", "sorted"=>"true", "when_empty"=>""}.freeze,
260
+ {"refusal"=>"InvariantViolation", "site"=>"group_by_collision", "argument"=>"key", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
257
261
  {"refusal"=>"Unauthorized", "site"=>"tenant_required", "argument"=>"query", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
258
262
  {"refusal"=>"Unauthorized", "site"=>"tenant_required", "argument"=>"field", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
259
263
  {"refusal"=>"Unauthorized", "site"=>"role_mismatch", "argument"=>"command", "shape"=>"scalar", "quoting"=>"none", "separator"=>"", "sorted"=>"false", "when_empty"=>""}.freeze,
@@ -314,6 +318,7 @@ module Hecks
314
318
  {"refusal"=>"InvariantViolation", "site"=>"value_object_invariant", "template"=>"{name} invariant violated — {description} (given {offered})"}.freeze,
315
319
  {"refusal"=>"InvariantViolation", "site"=>"admits_declared_set", "template"=>"{name} admits {admits} — {admitted} — got {offered}"}.freeze,
316
320
  {"refusal"=>"InvariantViolation", "site"=>"undeclared_set", "template"=>"{name} admits {admits}, which this chapter does not declare — a closed set is named Aggregate::SetName, and it must be one the bluebook actually holds"}.freeze,
321
+ {"refusal"=>"InvariantViolation", "site"=>"group_by_collision", "template"=>"{read_model} groups by {fields}, but rows {ids} share {key} — a group_by leaf holds one row; add a field that tells them apart"}.freeze,
317
322
  {"refusal"=>"Unauthorized", "site"=>"tenant_required", "template"=>"{query} declares authorize with tenant: {field} — pass {field}: to name which {field} this ask is scoped to"}.freeze,
318
323
  {"refusal"=>"Unauthorized", "site"=>"role_mismatch", "template"=>"{command} refused — role: {role}, and the caller stated {caller_role}"}.freeze,
319
324
  {"refusal"=>"Unauthorized", "site"=>"cross_tenant_reference", "template"=>"{aggregate} {field} is {tenant}, but {attribute} names a {target} whose own {target_field} is {other} — a cross-tenant reference"}.freeze,
data/lib/hecks.rb CHANGED
@@ -32,10 +32,16 @@ require_relative "hecks/facade/cli_door"
32
32
  require_relative "hecks/facade/cli_runner"
33
33
  require_relative "hecks/storehouse"
34
34
  require_relative "hecks/mcp_stdio_guard"
35
+ require_relative "hecks/mcp_door_scope"
35
36
  require_relative "hecks/framework"
36
- require_relative "hecks/corpus"
37
+ require_relative "hecks/vendoring"
37
38
  require_relative "hecks/embryonaut_bluebook"
38
39
 
40
+ # Repository-only tooling: the corpus table walks `examples/`, `qa/` and
41
+ # `spec/`, which only a checkout has, so it loads on first use and the
42
+ # packaged gem leaves it out (ADR 0066).
43
+ Hecks.autoload(:Corpus, File.expand_path("hecks/corpus", __dir__))
44
+
39
45
  # The root namespace and public facade of the whole DSL/runtime: `Hecks.boot`/
40
46
  # `.boot_files` assemble a running domain from `.bluebook`/`.hecksagon`/
41
47
  # `.world` files, and `.bluebook`/`.hecksagon`/`.port`/`.adapter`/`.world`/
@@ -57,7 +63,7 @@ module Hecks
57
63
  # `environments/<name>.hecksagon` / `.world` overlay it loads —
58
64
  # see Adapters::Folder#load_domain) existed on a prior commit of
59
65
  # this repo (933d1dd), was vendored out to a real consumer
60
- # (lifeadelics/domain), and was then lost from this repo's own
66
+ # (a client site's domain), and was then lost from this repo's own
61
67
  # history (no branch here reaches that commit). Ported forward
62
68
  # from the consumer's vendor snapshot — the only surviving copy —
63
69
  # and generalized: the original only loaded a `.hecksagon`
metadata CHANGED
@@ -1,12 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hecks
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.6.0
4
+ version: 2.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Young
8
8
  autorequire:
9
- bindir: bin
9
+ bindir: exe
10
10
  cert_chain: []
11
11
  date: 2026-09-27 00:00:00.000000000 Z
12
12
  dependencies:
@@ -30,10 +30,12 @@ description: |
30
30
  Nothing is scripted: no handler body, no class you write, no schema
31
31
  you migrate.
32
32
  email:
33
- executables: []
33
+ executables:
34
+ - hecks
34
35
  extensions: []
35
36
  extra_rdoc_files: []
36
37
  files:
38
+ - exe/hecks
37
39
  - lib/hecks.rb
38
40
  - lib/hecks/adapters.rb
39
41
  - lib/hecks/adapters/driven.rb
@@ -94,17 +96,6 @@ files:
94
96
  - lib/hecks/behaviors/ir.rb
95
97
  - lib/hecks/behaviors/rspec.rb
96
98
  - lib/hecks/behaviors/runner.rb
97
- - lib/hecks/bench.rb
98
- - lib/hecks/bench/cli.rb
99
- - lib/hecks/bench/environment.rb
100
- - lib/hecks/bench/postgres_probe.rb
101
- - lib/hecks/bench/report.rb
102
- - lib/hecks/bench/ruby_runner.rb
103
- - lib/hecks/bench/run.rb
104
- - lib/hecks/bench/rust_runner.rb
105
- - lib/hecks/bench/stats.rb
106
- - lib/hecks/bench/suite.rb
107
- - lib/hecks/bench/workload.rb
108
99
  - lib/hecks/bluebook.rb
109
100
  - lib/hecks/bluebook/aggregate.rb
110
101
  - lib/hecks/bluebook/assembly.rb
@@ -199,14 +190,27 @@ files:
199
190
  - lib/hecks/bluebook/synthesizer.rb
200
191
  - lib/hecks/bluebook/translation.rb
201
192
  - lib/hecks/bluebook/value_object.rb
202
- - lib/hecks/codemod.rb
193
+ - lib/hecks/cache_dir.rb
194
+ - lib/hecks/cli.rb
195
+ - lib/hecks/cli/document.rb
196
+ - lib/hecks/cli/ir.rb
197
+ - lib/hecks/cli/mcp.rb
198
+ - lib/hecks/cli/mcp_door.rb
199
+ - lib/hecks/cli/model_check.rb
200
+ - lib/hecks/cli/project_cli.rb
201
+ - lib/hecks/cli/project_diagrams.rb
202
+ - lib/hecks/cli/run.rb
203
+ - lib/hecks/cli/smoke_test.rb
204
+ - lib/hecks/cli/stores.rb
203
205
  - lib/hecks/construct.rb
204
- - lib/hecks/corpus.rb
205
206
  - lib/hecks/deploy/bluebook/deploy.bluebook
206
207
  - lib/hecks/deploy/bluebook/deploy.hecksagon
207
208
  - lib/hecks/deploy/oidc.json
208
- - lib/hecks/doc/reference.rb
209
209
  - lib/hecks/embryonaut_bluebook.rb
210
+ - lib/hecks/embryonaut_bluebook/lock.rb
211
+ - lib/hecks/embryonaut_bluebook/shape.rb
212
+ - lib/hecks/embryonaut_bluebook/vendor.rb
213
+ - lib/hecks/embryonaut_bluebook/vendor_cli.rb
210
214
  - lib/hecks/facade.rb
211
215
  - lib/hecks/facade/cli_door.rb
212
216
  - lib/hecks/facade/cli_runner.rb
@@ -242,47 +246,7 @@ files:
242
246
  - lib/hecks/framework/bluebook/privacy.bluebook
243
247
  - lib/hecks/framework/oidc.json
244
248
  - lib/hecks/freezer.rb
245
- - lib/hecks/fuzzing.rb
246
- - lib/hecks/fuzzing/bounded_exhaustive_expressions.rb
247
- - lib/hecks/fuzzing/combination_miner.rb
248
- - lib/hecks/fuzzing/concurrent_dispatch.rb
249
- - lib/hecks/fuzzing/coverage_campaign.rb
250
- - lib/hecks/fuzzing/differential.rb
251
- - lib/hecks/fuzzing/domain_generator.rb
252
- - lib/hecks/fuzzing/era_boundary.rb
253
- - lib/hecks/fuzzing/form_census.rb
254
- - lib/hecks/fuzzing/generated_domain_check.rb
255
- - lib/hecks/fuzzing/invalid_value_generator.rb
256
- - lib/hecks/fuzzing/isolated_boot.rb
257
- - lib/hecks/fuzzing/nondeterministic.rb
258
- - lib/hecks/fuzzing/persistence_parity.rb
259
- - lib/hecks/fuzzing/properties.rb
260
- - lib/hecks/fuzzing/properties/corrections.rb
261
- - lib/hecks/fuzzing/properties/dispatch_and_mutations.rb
262
- - lib/hecks/fuzzing/properties/guards.rb
263
- - lib/hecks/fuzzing/properties/invariants_and_aggregation.rb
264
- - lib/hecks/fuzzing/properties/lifecycle_and_replay.rb
265
- - lib/hecks/fuzzing/properties/outbox.rb
266
- - lib/hecks/fuzzing/properties/querying.rb
267
- - lib/hecks/fuzzing/qa_settings.rb
268
- - lib/hecks/fuzzing/replay.rb
269
- - lib/hecks/fuzzing/rotation_priority.rb
270
- - lib/hecks/fuzzing/rust_gap_manifest.rb
271
- - lib/hecks/fuzzing/self_consistency.rb
272
- - lib/hecks/fuzzing/sequence_generator.rb
273
- - lib/hecks/fuzzing/sequence_generator/adversary.rb
274
- - lib/hecks/fuzzing/sequence_generator/catalog.rb
275
- - lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb
276
- - lib/hecks/fuzzing/sequence_generator/picker.rb
277
- - lib/hecks/fuzzing/sequence_generator/query_binding.rb
278
- - lib/hecks/fuzzing/sequence_generator/step_builder.rb
279
- - lib/hecks/fuzzing/shrinker.rb
280
- - lib/hecks/fuzzing/structural_skips.rb
281
- - lib/hecks/fuzzing/sweep_depth.rb
282
- - lib/hecks/fuzzing/target_capabilities.rb
283
- - lib/hecks/fuzzing/value_generator.rb
284
249
  - lib/hecks/grammar.rb
285
- - lib/hecks/grammar/evolve.rb
286
250
  - lib/hecks/grammar/expression.bluebook
287
251
  - lib/hecks/grammar/expression_operators.json
288
252
  - lib/hecks/grammar/grammar.hecksagon
@@ -314,6 +278,7 @@ files:
314
278
  - lib/hecks/language/world/wiring.bluebook
315
279
  - lib/hecks/language/world/world.bluebook
316
280
  - lib/hecks/literal.rb
281
+ - lib/hecks/mcp_door_scope.rb
317
282
  - lib/hecks/mcp_stdio_guard.rb
318
283
  - lib/hecks/naming.rb
319
284
  - lib/hecks/ports.rb
@@ -353,6 +318,7 @@ files:
353
318
  - lib/hecks/ports/persistence/plugins/era/era_guard.rb
354
319
  - lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb
355
320
  - lib/hecks/ports/persistence/plugins/era/era_tamper.rb
321
+ - lib/hecks/ports/persistence/plugins/era/expected_era.rb
356
322
  - lib/hecks/ports/persistence/plugins/era/lineage.rb
357
323
  - lib/hecks/ports/persistence/plugins/era/postgres_era.rb
358
324
  - lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb
@@ -382,6 +348,8 @@ files:
382
348
  - lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb
383
349
  - lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb
384
350
  - lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb
351
+ - lib/hecks/ports/persistence/postgres_dump.rb
352
+ - lib/hecks/ports/persistence/postgres_dump/connection.rb
385
353
  - lib/hecks/ports/persistence/remote_runtime.rb
386
354
  - lib/hecks/ports/persistence/repository_factory.rb
387
355
  - lib/hecks/ports/persistence/state_codec.rb
@@ -393,8 +361,39 @@ files:
393
361
  - lib/hecks/projections.rb
394
362
  - lib/hecks/projections/bootstrap_table.rb
395
363
  - lib/hecks/projections/deploy/fargate.rb
364
+ - lib/hecks/projections/deploy/fargate/assembly.rb
365
+ - lib/hecks/projections/deploy/fargate/cdn.rb
366
+ - lib/hecks/projections/deploy/fargate/cdn_default.rb
367
+ - lib/hecks/projections/deploy/fargate/check.rb
368
+ - lib/hecks/projections/deploy/fargate/containers.rb
369
+ - lib/hecks/projections/deploy/fargate/extras.rb
370
+ - lib/hecks/projections/deploy/fargate/monitoring.rb
371
+ - lib/hecks/projections/deploy/fargate/settings.rb
372
+ - lib/hecks/projections/deploy/fargate/yaml.rb
396
373
  - lib/hecks/projections/deploy/lambda.rb
374
+ - lib/hecks/projections/deploy/preview.rb
375
+ - lib/hecks/projections/deploy/preview/access_yaml.rb
376
+ - lib/hecks/projections/deploy/preview/containers.rb
377
+ - lib/hecks/projections/deploy/preview/preview.sh.erb
378
+ - lib/hecks/projections/deploy/preview/routing_yaml.rb
379
+ - lib/hecks/projections/deploy/preview/script.rb
380
+ - lib/hecks/projections/deploy/preview/settings.rb
381
+ - lib/hecks/projections/deploy/preview/task_yaml.rb
382
+ - lib/hecks/projections/deploy/preview/template.rb
383
+ - lib/hecks/projections/deploy/preview/yaml_text.rb
384
+ - lib/hecks/projections/deploy/scripts.rb
385
+ - lib/hecks/projections/deploy/scripts/deploy-service.sh.tmpl
386
+ - lib/hecks/projections/deploy/scripts/expected-era.header
387
+ - lib/hecks/projections/deploy/scripts/hosting.mk.tmpl
388
+ - lib/hecks/projections/deploy/scripts/settings.rb
389
+ - lib/hecks/projections/deploy/scripts/smoke-after-deploy.sh.tmpl
397
390
  - lib/hecks/projections/deploy/shared.rb
391
+ - lib/hecks/projections/deploy/smoke.rb
392
+ - lib/hecks/projections/deploy/smoke/harness.js
393
+ - lib/hecks/projections/deploy/smoke/workflow.yml.tmpl
394
+ - lib/hecks/projections/deploy/template_diff.rb
395
+ - lib/hecks/projections/deploy/template_diff/comparer.rb
396
+ - lib/hecks/projections/deploy/template_diff/loader.rb
398
397
  - lib/hecks/projections/diagrams.rb
399
398
  - lib/hecks/projections/glossary.rb
400
399
  - lib/hecks/projections/glossary/html.rb
@@ -422,7 +421,6 @@ files:
422
421
  - lib/hecks/projector/ir_projector.rb
423
422
  - lib/hecks/projector/narrate_projector.rb
424
423
  - lib/hecks/projector/target.rb
425
- - lib/hecks/query_ir.rb
426
424
  - lib/hecks/query_specification.rb
427
425
  - lib/hecks/query_specification/common/authorization_spec.rb
428
426
  - lib/hecks/query_specification/common/comparators.rb
@@ -441,6 +439,18 @@ files:
441
439
  - lib/hecks/query_specification/field_path.rb
442
440
  - lib/hecks/query_specification/hop_path.rb
443
441
  - lib/hecks/query_specification/read_model/specification.rb
442
+ - lib/hecks/release/gem_pin.rb
443
+ - lib/hecks/release/gem_pin/published_versions.rb
444
+ - lib/hecks/release/runner.rb
445
+ - lib/hecks/release/runner/ci_publisher.rb
446
+ - lib/hecks/release/runner/commands.rb
447
+ - lib/hecks/release/runner/console.rb
448
+ - lib/hecks/release/runner/gem_publisher.rb
449
+ - lib/hecks/release/runner/git.rb
450
+ - lib/hecks/release/runner/npm_publisher.rb
451
+ - lib/hecks/release/runner/preflight.rb
452
+ - lib/hecks/release/runner/published.rb
453
+ - lib/hecks/release/runner/tagger.rb
444
454
  - lib/hecks/rendering.rb
445
455
  - lib/hecks/router.rb
446
456
  - lib/hecks/router/namespace_installer.rb
@@ -481,6 +491,7 @@ files:
481
491
  - lib/hecks/runtime/registry.rb
482
492
  - lib/hecks/runtime/registry/saga_persistence.rb
483
493
  - lib/hecks/runtime/registry/verification.rb
494
+ - lib/hecks/runtime/registry/world_defaults.rb
484
495
  - lib/hecks/runtime/remote_dispatcher.rb
485
496
  - lib/hecks/runtime/routing.rb
486
497
  - lib/hecks/runtime/saga_interpreter.rb
@@ -496,6 +507,9 @@ files:
496
507
  - lib/hecks/storehouse.rb
497
508
  - lib/hecks/tenancy/bluebook/tenancy.bluebook
498
509
  - lib/hecks/tenancy/bluebook/tenancy.hecksagon
510
+ - lib/hecks/vendoring.rb
511
+ - lib/hecks/vendoring/git_environment.rb
512
+ - lib/hecks/vendoring/git_source.rb
499
513
  - lib/hecks/version.rb
500
514
  - lib/hecks/vocabulary.rb
501
515
  - lib/rubocop/cop/hecks/fallback_hash_lookup.rb
@@ -1,74 +0,0 @@
1
- require "optparse"
2
- require_relative "suite"
3
- require_relative "report"
4
-
5
- module Hecks
6
- module Bench
7
- # The command line behind `bin/bench`: parses flags, runs the `Suite`, prints the report.
8
- #
9
- # Kept in `lib/` so a spec can drive it with a tiny configuration and read what it
10
- # prints, rather than shelling out to a script.
11
- module CLI
12
- # The defaults `bin/bench` runs with when no flag says otherwise.
13
- DEFAULTS = { domains: %w[pizzas banking], targets: Suite::TARGETS, warmup: 200, iterations: 1000,
14
- runs: 3 }.freeze
15
-
16
- module_function
17
-
18
- # Runs the benchmark described by the command line and prints its report.
19
- #
20
- # @param argv [Array<String>] the command-line arguments
21
- # @param out [#puts] where the report goes
22
- # @param err [#puts] where progress and usage errors go
23
- # @return [Integer] the process exit status: 0 on success, 2 for a usage error
24
- def run(argv, out: $stdout, err: $stderr)
25
- options = parse(argv)
26
- result = Suite.call(options.fetch(:config), log: err)
27
- out.puts(options[:format] == "json" ? Report.json(result) : Report.markdown(result))
28
- File.write(options[:output], Report.json(result)) if options[:output]
29
- 0
30
- rescue OptionParser::ParseError, ArgumentError => e
31
- err.puts "bin/bench: #{e.message}"
32
- 2
33
- end
34
-
35
- # Turns command-line arguments into a configuration and output choices.
36
- #
37
- # @param argv [Array<String>] the command-line arguments
38
- # @return [Hash{Symbol => Object}] `:config` (a `Suite::Config`), `:format` and `:output`
39
- # @raise [OptionParser::ParseError] on an unknown or malformed flag
40
- def parse(argv)
41
- values = DEFAULTS.dup
42
- extras = { format: "markdown", output: nil, rust_binary: nil }
43
- parser(values, extras).parse(argv.dup)
44
- { config: Suite::Config.new(**values, rust_binary: extras[:rust_binary]),
45
- format: extras[:format], output: extras[:output] }
46
- end
47
-
48
- # Builds the flag parser.
49
- #
50
- # @param values [Hash{Symbol => Object}] the `Suite::Config` fields, filled in as flags parse
51
- # @param extras [Hash{Symbol => Object}] the output choices, filled in as flags parse
52
- # @return [OptionParser] the parser
53
- def parser(values, extras)
54
- OptionParser.new do |opts|
55
- opts.banner = "usage: bin/bench [options]"
56
- opts.on("--domain NAMES", Array, "pizzas, banking (default: both)") { |v| values[:domains] = v }
57
- opts.on("--targets NAMES", Array, "#{Suite::TARGETS.join(', ')} (default: all)") { |v| values[:targets] = v }
58
- opts.on("--iterations N", Integer, "timed cycles per run (default #{DEFAULTS[:iterations]})") do |v|
59
- values[:iterations] = v
60
- end
61
- opts.on("--warmup N", Integer, "discarded cycles before timing (default #{DEFAULTS[:warmup]})") do |v|
62
- values[:warmup] = v
63
- end
64
- opts.on("--runs N", Integer, "fresh boots per target, median reported (default #{DEFAULTS[:runs]})") do |v|
65
- values[:runs] = v
66
- end
67
- opts.on("--rust-binary PATH", "use this `rust` binary instead of building one") { |v| extras[:rust_binary] = v }
68
- opts.on("--format FORMAT", %w[markdown json], "markdown (default) or json") { |v| extras[:format] = v }
69
- opts.on("--output PATH", "also write the full JSON result here") { |v| extras[:output] = v }
70
- end
71
- end
72
- end
73
- end
74
- end
@@ -1,100 +0,0 @@
1
- require "etc"
2
- require "open3"
3
-
4
- module Hecks
5
- module Bench
6
- # A description of the machine and toolchain a benchmark ran on.
7
- #
8
- # A number without its hardware is not reproducible, so every report carries
9
- # this. Each probe is best effort: a missing tool becomes `"unknown"` rather
10
- # than an error, since the benchmark itself is still valid without it.
11
- module Environment
12
- module_function
13
-
14
- # Collects the machine and toolchain facts a report should carry.
15
- #
16
- # @return [Hash{Symbol => Object}] `:cpu`, `:cores`, `:memory_gib`, `:os`, `:ruby`,
17
- # `:yjit`, `:rustc`, `:cargo`, `:hecks`, `:commit` and `:load_average`
18
- def describe
19
- {
20
- cpu: cpu, cores: Etc.nprocessors, memory_gib: memory_gib, os: os,
21
- ruby: RUBY_DESCRIPTION, yjit: yjit?,
22
- rustc: capture("rustc", "-V"), cargo: capture("cargo", "-V"),
23
- hecks: Hecks::VERSION, commit: commit, load_average: load_average
24
- }
25
- end
26
-
27
- # Reads the one-minute load average, the quickest sign that something else was
28
- # busy while a benchmark ran. `Suite.call` reads it before and after and reports both.
29
- #
30
- # @return [Float, nil] the one-minute load average, or nil when it cannot be read
31
- def load_average
32
- text = RUBY_PLATFORM.include?("darwin") ? capture("sysctl", "-n", "vm.loadavg").delete("{}") : File.read("/proc/loadavg")
33
- text.split.first.to_f.round(2)
34
- rescue SystemCallError
35
- nil
36
- end
37
-
38
- # Names the processor.
39
- #
40
- # @return [String] the CPU model, or `"unknown"`
41
- def cpu
42
- return capture("sysctl", "-n", "machdep.cpu.brand_string") if RUBY_PLATFORM.include?("darwin")
43
-
44
- model = File.foreach("/proc/cpuinfo").find { |line| line.start_with?("model name") }
45
- model ? model.split(":", 2).last.strip : "unknown"
46
- rescue SystemCallError
47
- "unknown"
48
- end
49
-
50
- # Reads installed memory.
51
- #
52
- # @return [Float, String] physical memory in GiB, or `"unknown"`
53
- def memory_gib
54
- bytes =
55
- if RUBY_PLATFORM.include?("darwin")
56
- capture("sysctl", "-n", "hw.memsize").to_i
57
- else
58
- File.read("/proc/meminfo")[/MemTotal:\s+(\d+)/, 1].to_i * 1024
59
- end
60
- bytes.zero? ? "unknown" : (bytes / (1024.0**3)).round(1)
61
- rescue SystemCallError
62
- "unknown"
63
- end
64
-
65
- # Names the operating system.
66
- #
67
- # @return [String] the OS name and version, or `"unknown"`
68
- def os
69
- return "macOS #{capture('sw_vers', '-productVersion')} (#{capture('uname', '-m')})" if RUBY_PLATFORM.include?("darwin")
70
-
71
- capture("uname", "-sr")
72
- end
73
-
74
- # Says whether Ruby's `YJIT` compiler was running.
75
- #
76
- # @return [Boolean] true when `YJIT` is enabled in this process
77
- def yjit?
78
- defined?(RubyVM::YJIT) ? RubyVM::YJIT.enabled? : false
79
- end
80
-
81
- # Names the Hecks source revision under test.
82
- #
83
- # @return [String] the short commit hash, or `"unknown"` outside a git checkout
84
- def commit
85
- capture("git", "-C", File.expand_path("../../..", __dir__), "rev-parse", "--short", "HEAD")
86
- end
87
-
88
- # Runs a command and returns its first line of output.
89
- #
90
- # @param command [Array<String>] the program and its arguments
91
- # @return [String] the trimmed first line of stdout, or `"unknown"` if it cannot run
92
- def capture(*command)
93
- out, status = Open3.capture2(*command, err: File::NULL)
94
- status.success? && !out.strip.empty? ? out.lines.first.strip : "unknown"
95
- rescue SystemCallError
96
- "unknown"
97
- end
98
- end
99
- end
100
- end
@@ -1,41 +0,0 @@
1
- module Hecks
2
- module Bench
3
- # Decides whether the Postgres targets can run at all.
4
- #
5
- # Postgres is optional. A machine with no server, or without the `pg` gem, gets a
6
- # skipped target and a sentence saying why, never a stack trace. Connection
7
- # settings come from libpq's own environment (`PGHOST`, `PGPORT`, `PGUSER`,
8
- # `PGPASSWORD`), the same way the fuzzer's Postgres adapters read them.
9
- module PostgresProbe
10
- module_function
11
-
12
- # Tries to reach the server's maintenance database.
13
- #
14
- # @return [String, nil] nil when a server answered, otherwise one sentence saying why
15
- # the Postgres targets cannot run
16
- def unavailable_reason
17
- require "pg"
18
- PG.connect(dbname: "postgres", connect_timeout: 2).close
19
- nil
20
- rescue LoadError
21
- "the `pg` gem is not installed"
22
- rescue PG::Error => e
23
- "no Postgres server is reachable (#{e.message.lines.first.to_s.strip}); start one, or point " \
24
- "PGHOST, PGPORT and PGUSER at one"
25
- end
26
-
27
- # Reads the server's version for the report's environment block.
28
- #
29
- # @return [String] the `server_version` setting, or `"unknown"` if it cannot be read
30
- def server_version
31
- require "pg"
32
- connection = PG.connect(dbname: "postgres", connect_timeout: 2)
33
- connection.exec("SHOW server_version").getvalue(0, 0)
34
- rescue LoadError, PG::Error
35
- "unknown"
36
- ensure
37
- connection&.close
38
- end
39
- end
40
- end
41
- end