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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2220925ed910b9c63dd34c3fc75448f6cff634a64be3fb67461985d462e83563
4
- data.tar.gz: 618319249d19f123171d300578ba8d70556391371457700504c92ba4bd389935
3
+ metadata.gz: 66f85d62ad01467ff2ae17c6d3be63c706bea69a9e6f7b20839d9f5fc22234a5
4
+ data.tar.gz: 45413f0bd639bfe548ca9f8f7970d5136ed6aa30a25765870ca0212806af3c90
5
5
  SHA512:
6
- metadata.gz: a24cd51e0ba290e819645aec45cbc8a55c9978cb1c5fed673180db103a050a77516ebcd224d0102fad523161ce4776866b5702acf790dd0751282c2c399e73a9
7
- data.tar.gz: a779523871cd0e81d87c26305bed16e51916723ef544e55ccc30d669b6fdb38b825ee2a05515ae9f8c2f40ff31e4faa57f4d5dffc0dac68146d900d112830d92
6
+ metadata.gz: b817baff1d4e990f1161080d23f9f10fadd2e1eb8a6f76b1ed551fe021992311f10d64f0eef63218e515905fa2757d879a607abc4b40ecfeb4d0d45a6011a8a6
7
+ data.tar.gz: '0819f496494a76afe81697f8a83301c07acef480b218501748616f1537f0c5d3c0148d67271dea0fd4eea6b6bcb9bbb278331a203883b3c169c08cd59f384451'
data/exe/hecks ADDED
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # The `hecks` command the gem installs: run, read, check and serve a domain you
4
+ # supply. `hecks` with no arguments lists the subcommands; `hecks <command> --help`
5
+ # prints one's usage. The router is `Hecks::CLI` (lib/hecks/cli.rb).
6
+ #
7
+ # The gem's own `lib` goes first on the load path, as it does for the `bin/`
8
+ # scripts, so this file also runs straight from a checkout.
9
+
10
+ $LOAD_PATH.unshift File.expand_path("../lib", __dir__)
11
+ require "hecks/cli"
12
+
13
+ exit Hecks::CLI.start(ARGV)
@@ -6,7 +6,7 @@ module Hecks
6
6
  module Adapters
7
7
  # **Google's own OIDC handshake** — the `authentication` port's one real
8
8
  # implementation today. Consolidates what was hand-rolled per-app
9
- # (an embryonaut_console `google_auth.rb` did this on its own) into
9
+ # (a console app's `google_auth.rb` did this on its own) into
10
10
  # one adapter, so any hecks-based app gets Google sign-in for free, the
11
11
  # same "one adapter, reusable everywhere" value every other adapter
12
12
  # in this directory already has.
@@ -29,7 +29,7 @@ module Hecks
29
29
  # exist precisely so a domain whose AWS identity predates a rename
30
30
  # keeps targeting the stack that is actually live rather than
31
31
  # standing up a second, empty one beside it. A real one:
32
- # embryonautfoundersapp deploys as `hecksagain-embryonaut`, and no
32
+ # a client site deploys under a fixed stack name, and no
33
33
  # value of `domain` (or of `DOMAIN_NAME`, the deployed-Lambda
34
34
  # override callers already pass) can make this computation produce
35
35
  # a name with no dash after "hecks". Every Ruby-side read and
@@ -217,7 +217,7 @@ module Hecks
217
217
  #
218
218
  # @param id [Integer] the row id `outbox_enqueue` assigned
219
219
  # @return [Boolean] true when the row was pending and is now claimed; false when it is
220
- # unknown or no longer pending
220
+ # unknown or not pending
221
221
  def outbox_claim(id) # rubocop:disable Naming/PredicateMethod
222
222
  row = @outbox.find { |held| held.id == id }
223
223
  return false unless row&.pending?
@@ -247,7 +247,7 @@ module Hecks
247
247
  # an update to apply; nil writes unconditionally. Ignored for a delete
248
248
  # @return [Runtime::Instance, PG::Result, nil] for a save, a new instance over the
249
249
  # entry's state with `version` set to the stored `hecks_version`, or nil when
250
- # `expected_version` no longer matched and nothing was written; for a delete, the
250
+ # `expected_version` did not match and nothing was written; for a delete, the
251
251
  # `DELETE` statement's `PG::Result`
252
252
  # @raise [PG::Error] if the statement fails
253
253
  # rubocop:disable Metrics/AbcSize -- the CAS/plain upsert split is one
@@ -72,7 +72,7 @@ module Hecks
72
72
  # That's invisible to anything that virtualizes the filesystem at
73
73
  # the Ruby level instead of the OS level (e.g. tebako's memfs,
74
74
  # which presses a hecks-based app into a single executable —
75
- # see domain/README.md's "Deploying" section in lifeadelics for
75
+ # see domain/README.md's "Deploying" section in a client site's domain for
76
76
  # why that matters). ::Prism.parse(File.read(file)) parses the
77
77
  # exact same bytes, just read through Ruby's File.read first,
78
78
  # which those tools do intercept.
@@ -85,7 +85,7 @@ module Hecks
85
85
  # never edited out from under it), but wrong for anything that
86
86
  # legitimately reloads an edited file in-process: a stale cached
87
87
  # tree reports a `given`/`ensures` block at its old line number,
88
- # which no longer matches the freshly re-executed file's own
88
+ # which does not match the freshly re-executed file's own
89
89
  # `block.source_location` — surfacing as "did not survive
90
90
  # extraction" on a perfectly valid file. Built for real building
91
91
  # `Hecks::Codemod` (lib/hecks/codemod.rb), which needs exactly this
@@ -15,7 +15,7 @@ module Hecks
15
15
  # Rebuilds a read store from the authoritative journal, entry by entry.
16
16
  # A value object is written as its JSON object and a reference as the
17
17
  # bare id it holds — the same shapes the command path writes, so there
18
- # is no second representation to accept here any more.
18
+ # is no second representation to accept here.
19
19
  class SqliteProjection < Sqlite
20
20
  # Replaces or deletes the read store's row for one journal entry, encoding the entry's
21
21
  # state directly rather than through a `Runtime::Instance`.
@@ -4,7 +4,7 @@ require "fileutils"
4
4
 
5
5
  module Hecks
6
6
  module Adapters
7
- # THE IMPERATIVE HALF of provisioning a tenant, pulled out of
7
+ # The imperative half of provisioning a tenant, pulled out of
8
8
  # `bin/project_tenant` and behind a real driven port
9
9
  # (`Deploy::Tenant.port "TenantProvisioning"`) instead — the same
10
10
  # hexagonal reasoning `GithubChecks` already gives for its own
@@ -16,34 +16,55 @@ module Hecks
16
16
  # `PortOperationInterpreter#ask`'s own "every failure is an answer"
17
17
  # comment for why nothing here needs its own rescue.
18
18
  #
19
- # DELIBERATELY DOES NOT BOOT THE TARGET DOMAIN — that step (proving
19
+ # ## What it leaves out
20
+ #
21
+ # Deliberately does not boot the target domain — that step (proving
20
22
  # it boots for real, running the tenant_capable? gate) stays in
21
- # `bin/project_tenant` itself, called AFTER this operation answers,
23
+ # `bin/project_tenant` itself, called after this operation answers,
22
24
  # not nested inside it. Booting a whole domain from inside an
23
25
  # adapter method that is itself running mid-dispatch (this port
24
26
  # operation) is a real, separate concern from writing one file, and
25
27
  # keeping the two apart avoids a nested `Hecks.boot` call ever
26
28
  # running inside another boot's own dispatch call stack.
27
29
  #
28
- # RETURNS A HASH SHAPED LIKE `Tenancy::Tenant.Register`'S OWN
29
- # ARGUMENTS, on purpose — `tenancy.hecksagon`'s own `translates`
30
+ # ## Return shape
31
+ #
32
+ # Returns a hash shaped like `Tenancy::Tenant.Register`'s own
33
+ # arguments, on purpose — `tenancy.hecksagon`'s own `translates`
30
34
  # reaction forwards an answered event's payload verbatim, so this
31
- # adapter's own return value IS the translation from Deploy's
35
+ # adapter's own return value is the translation from Deploy's
32
36
  # vocabulary into Tenancy's, decided here rather than in a mapping
33
37
  # layer neither side could see into.
34
38
  class TenantProvisioner
39
+ # Accepts the arguments every driven adapter is built with and keeps none of them.
40
+ #
41
+ # @param aggregate [Object, nil] unused
42
+ # @param settings [Hash] unused
43
+ # @param root [String, nil] unused
35
44
  def initialize(aggregate: nil, settings: {}, root: nil); end
36
45
 
37
- # `directory:` IS REQUIRED, NOT DERIVED FROM `domain` — a real,
46
+ # Writes the tenant's environment overlay file under its domain directory.
47
+ #
48
+ # `directory:` is required, not derived from `domain` — a real,
38
49
  # confirmed bug found only under CI's own real-Postgres suite: a
39
- # domain's own DECLARED NAME (`domain`, e.g. "Scratch") is not a
50
+ # domain's own declared name (`domain`, e.g. "Scratch") is not a
40
51
  # filesystem path, and File.expand_path(domain, Dir.pwd) silently
41
52
  # resolved to the wrong directory (relative to whatever the
42
- # RUNNING PROCESS' own cwd happened to be) whenever the CLI's own
53
+ # running process' own cwd happened to be) whenever the CLI's own
43
54
  # `--domain=` value didn't happen to equal its own directory
44
55
  # argument by coincidence. `bin/project_tenant` passes its own
45
56
  # real `domain_directory` local straight through.
46
-
57
+ #
58
+ # Every argument arrives either bare or wrapped as `{ value: ... }`; both are read.
59
+ #
60
+ # @param slug [String, Hash] the tenant's slug, which names the overlay file
61
+ # @param domain [String, Hash] the declared domain name the overlay is for
62
+ # @param realm [String, Hash] the realm the overlay declares
63
+ # @param schema [String, Hash] the schema the overlay declares
64
+ # @param database [String, Hash] the database the overlay declares
65
+ # @param adapter [String, Hash] the persistence adapter the overlay declares
66
+ # @param directory [String, Hash] the domain's own directory on disk
67
+ # @return [Hash{Symbol => Object}] `:slug`, `:domain`, `:realm` and `:schema`, as given
47
68
  def provision(slug:, domain:, realm:, schema:, database:, adapter:, directory:)
48
69
  domain_directory = File.expand_path(directory[:value] || directory)
49
70
 
@@ -228,7 +228,7 @@ module Hecks
228
228
  # the dispatch's own result
229
229
  # @return [Hash{Symbol => Object}] the settled record's current state, read
230
230
  # back from the repository; `result.state` (or `{}`) when the result has no
231
- # id or the repository no longer has that aggregate/record
231
+ # id or the repository does not have that aggregate/record
232
232
  def settled_state(runtime, verb, result)
233
233
  return result.state || {} unless result.respond_to?(:id) && result.id
234
234
 
@@ -266,7 +266,7 @@ module Hecks
266
266
  # only so long as nothing else ever asked it to resolve a port-operation
267
267
  # verb. Now that a `policy` can legitimately `trigger` a port operation
268
268
  # (`ReactionInvocation#resolve_target`'s own port-operation branch),
269
- # that raise no longer happens, so this checks directly instead.
269
+ # that raise does not happen, so this checks directly instead.
270
270
  #
271
271
  # @param runtime [Runtime::Dispatcher, Runtime::RemoteDispatcher] the suite's
272
272
  # booted runtime
@@ -151,7 +151,7 @@ module Hecks
151
151
  # Entity's contract claims `owner: :parent`
152
152
  #
153
153
  # `shape` and `handler` are not on this list — S17 (ADR 0026) made Member and
154
- # Dispatch nested entities, so neither is a parent field any more the way
154
+ # Dispatch nested entities, so neither is a parent field the way
155
155
  # `owner` is. `spec/assembly_spec` derives this set from `Plan` and the
156
156
  # contracts directly and fails on any drift, rather than trusting this list to
157
157
  # stay in sync with a second hand-written copy kept by the model generator.
@@ -243,7 +243,7 @@ module Hecks
243
243
 
244
244
  # S17, ADR 0026 — Handler is a genuine entity now, nested under
245
245
  # ProcessManager (`entity "Handler"`, reaction.bluebook). Neither
246
- # `position` nor `handler` is a stored field any more: a saga
246
+ # `position` nor `handler` is a stored field: a saga
247
247
  # answers each event once, so `event_type` is Handler's own real,
248
248
  # non-positional identity (no walk-minted `position` to derive),
249
249
  # and the process manager it belongs to is structural now — which
@@ -429,10 +429,10 @@ module Hecks
429
429
  # A member's pairs are an open map, which is why Member is its own root in
430
430
  # the language. The IR keeps them as a plain hash on the value object, so
431
431
  # they are assembled with their shape rather than as a construct.
432
- # S17, ADR 0026 — Member is a genuine entity now, nested under
433
- # ValueObject (`entity "Member"`, shape.bluebook). It no longer
434
- # holds a `shape` field at all (that was the free-text, un-parsed
435
- # spelling a standalone root once needed ; an entity's element is
432
+ # S17, ADR 0026 — Member is a genuine entity, nested under
433
+ # ValueObject (`entity "Member"`, shape.bluebook). It holds no
434
+ # `shape` field at all (a free-text, un-parsed spelling would suit
435
+ # only a standalone root ; an entity's element is
436
436
  # never serialized as text) — only `position` (walk-minted, see
437
437
  # `entity_own_identity`, judge.rb) and `pairs` (still an open map,
438
438
  # still one row per entry, still why a value object cannot hold it
@@ -21,8 +21,8 @@ module Hecks
21
21
  module Specializer
22
22
  module_function
23
23
 
24
- # S17, ADR 0026 — `Handler` is a genuine entity now, nested under
25
- # `ProcessManager`, so `.aggregate` alone no longer finds it —
24
+ # S17, ADR 0026 — `Handler` is a genuine entity, nested under
25
+ # `ProcessManager`, so `.aggregate` alone does not find it —
26
26
  # it hangs off some aggregate's own `.entities` instead
27
27
  # (searched recursively, the same reason `Value::Coercion#find_
28
28
  # entity` does: a nested entity, like `Dispatch` inside
@@ -31,7 +31,7 @@ module Hecks
31
31
  # ## What stays hand-written
32
32
  #
33
33
  # The containment — which construct holds which — stays hand-written; it is
34
- # not a field table. The runtime surface is no longer built here at all — the
34
+ # not a field table. The runtime surface is not built here at all — the
35
35
  # door is a per-boot projection, facade/surface.rb.
36
36
  class Assembly
37
37
  # Builds the graph the runtime runs from one chapter's declared hash.
@@ -91,15 +91,18 @@ module Hecks
91
91
  @ports_by_name[port.name] = port
92
92
  end
93
93
 
94
- # A TRANSLATED REACTION IS ALSO DECLARED IN THE HECKSAGON —
94
+ # A translated reaction is also declared in the hecksagon —
95
95
  # `HecksagonBuilder#translates` builds an ordinary `Policy` (same
96
96
  # shape, same `PolicyInterpreter` runtime, as one written inside a
97
97
  # `policy` block in this chapter's own `.bluebook`) and attaches it
98
98
  # here, after the chapter already exists, the same reasoning
99
99
  # `add_port` gives one method up. Kept out of the bluebook itself
100
- # on purpose: which FOREIGN domain's event this chapter reacts to
100
+ # on purpose: which foreign domain's event this chapter reacts to
101
101
  # is a wiring/context-mapping decision, not a fact the domain
102
102
  # states about its own model.
103
+ #
104
+ # @param policy [Bluebook::Policy] the translated reaction to attach
105
+ # @return [Array<Bluebook::Policy>] this chapter's policies, with `policy` appended
103
106
  def add_policy(policy)
104
107
  @policies << policy
105
108
  end
@@ -9,6 +9,24 @@ module Hecks
9
9
  # @return [Array<Symbol>] each declared `group_by` field's name, in declaration order
10
10
  def group_by_fields = @group_by.map { |row| row[:field].to_sym }
11
11
 
12
+ # Reports whether this read model's `group_by` names every identity head
13
+ # of the aggregate it groups (ADR 0061, decision D1).
14
+ #
15
+ # Such a key path cannot be shared by two rows, so it is accepted from the
16
+ # declaration alone and never checked for a collision at dispatch. Any
17
+ # other key path is checked per request.
18
+ #
19
+ # @param aggregate [Bluebook::Aggregate, nil] the aggregate of this read
20
+ # model's one many-side head
21
+ # @return [Boolean] false when `aggregate` is nil or declares no identity,
22
+ # since uniqueness cannot then be shown
23
+ def groups_by_identity?(aggregate)
24
+ return false unless aggregate
25
+
26
+ identity = Array(aggregate.identity_heads).map(&:to_sym)
27
+ !identity.empty? && (identity - group_by_fields).empty?
28
+ end
29
+
12
30
  # `!!` rather than a bare `@count` — the DSL/reconstruction
13
31
  # boundary (ReadModel#initialize) already normalises to
14
32
  # `true`/`nil`, so this is belt and braces against a future
@@ -19,11 +19,11 @@ module Hecks
19
19
  # Who may sign in, and with what role — rust/host's Google-OAuth
20
20
  # provision/member_rows resolve this instead of an env var naming
21
21
  # the aggregate (HECKS_MEMBERSHIP_AGGREGATE). Same declared-
22
- # not-named shape AUTHORIZATION already is for Governance.
22
+ # not-named shape `AUTHORIZATION` already is for Governance.
23
23
  MEMBERSHIP = "membership".freeze
24
24
  # A stable organizational identity, independent of how it was
25
25
  # authenticated — recognised by declaration, not the literal name
26
- # "Identity". Same declared-not-named shape AUTHORIZATION already
26
+ # "Identity". Same declared-not-named shape `AUTHORIZATION` already
27
27
  # is. rust/host does not build this chapter's payloads; any field
28
28
  # mapping lives on the consuming hecksagon's `translates` ACL.
29
29
  IDENTITY = "identity".freeze
@@ -4,7 +4,7 @@ require_relative "../ir"
4
4
 
5
5
  module Hecks
6
6
  module Bluebook
7
- # The chapter, and no longer the namespace it lives in.
7
+ # The chapter, which is not the namespace it lives in.
8
8
  #
9
9
  # `Hecks::Bluebook` was briefly a class, because dropping the
10
10
  # old `IR::` segment would otherwise have produced
@@ -198,7 +198,7 @@ module Hecks
198
198
  # never `[]`). Wave 6 (identity-and-relationships arc) un-deprecates
199
199
  # all three for real: a relationship word now retains the author's
200
200
  # domain concept in IR — still stored as one or more target
201
- # identities, but no longer collapsed to a bare `reference_to`
201
+ # identities, but not collapsed to a bare `reference_to`
202
202
  # during assembly. `MetaValidator.shadow_parsing?` still routes to
203
203
  # `legacy_has_many`/`legacy_has_one` so frozen era text written
204
204
  # under the old (lying/collapsing) meaning still parses the way it
@@ -511,7 +511,7 @@ module Hecks
511
511
  # are this construct's own refusal wording, not shared, since
512
512
  # `declared_by:` only exists here so far. Unresolved (no
513
513
  # candidate yet, or `declared_by:` naming an aggregate that
514
- # hasn't declared it yet) is no longer a fourth branch that
514
+ # hasn't declared it yet) is not a fourth branch that
515
515
  # raises here — see `#pending_chapter_given`, below, for why:
516
516
  # a chapter split across files can genuinely reference a
517
517
  # precondition a later file declares, and "not found among
@@ -77,7 +77,7 @@ module Hecks
77
77
  end
78
78
 
79
79
  def method_missing(verb, *args, **kwargs, &block)
80
- # A BARE CALL — no args, no kwargs, no block — starts (or
80
+ # **A bare call** — no args, no kwargs, no block — starts (or
81
81
  # continues, on `AttributePath` itself below) a Privacy
82
82
  # marking chain: `Registration.attendee.medications.has_phi(
83
83
  # readable_by: "Privacy officer")`. No existing real
@@ -115,10 +115,15 @@ module Hecks
115
115
  @path = path
116
116
  end
117
117
 
118
+ # Records a `has_<category>` marking, or extends the attribute path by one segment.
119
+ #
118
120
  # @param verb [Symbol] `has_<category>` to record the marking and end the chain;
119
121
  # any other bare name to extend the path one segment further
120
122
  # @param readable_by [String] required only for a `has_<category>` call — the
121
123
  # Governance role a read must hold to see this field unredacted
124
+ # @param args [Array] must be empty; a positional argument is refused
125
+ # @param kwargs [Hash] must be empty; any keyword but `readable_by:` is refused
126
+ # @param block [Proc, nil] must be absent; a block is refused
122
127
  # @return [Bluebook::DSL::AttributePath, nil] a longer chain for a plain segment;
123
128
  # `nil` (nothing further to chain) for a `has_<category>` call
124
129
  # @raise [Malformed] if a `has_<category>` call omits `readable_by:`, or any call
@@ -431,9 +431,9 @@ module Hecks
431
431
  # manager's own structural check fails
432
432
  def self.build(name, version: nil, &block)
433
433
  registry = Hecks.current_registry
434
- # WHICH FILE CALLED `Hecks.bluebook`, recorded for
434
+ # Which file called `Hecks.bluebook`, recorded for
435
435
  # `Registry#record_bluebook_source` — two frames up: this
436
- # method's own caller is `Hecks.bluebook` (hecks.rb), and ITS
436
+ # method's own caller is `Hecks.bluebook` (hecks.rb), and its
437
437
  # caller is the real `.bluebook` file's own top-level call site.
438
438
  caller_location = caller_locations(2, 1)&.first
439
439
  registry&.record_bluebook_source(name, caller_location&.path)
@@ -82,6 +82,8 @@ module Hecks
82
82
  ["Type", "one_of"] => :one_of_impl,
83
83
  ["World", "realm"] => :realm_impl,
84
84
  ["World", "latest"] => :latest_impl,
85
+ ["World", "default_database"] => :default_database_impl,
86
+ ["World", "default_adapter"] => :default_adapter_impl,
85
87
  ["DomainPort", "operation"] => :tells_impl,
86
88
  ["DomainPort", "tells"] => :tells_impl,
87
89
  ["DomainPort", "asks"] => :asks_impl,
@@ -22,7 +22,7 @@ module Hecks
22
22
  # same as an absent `to:` and falls through to `from` (also
23
23
  # absent), so `then_set :accepted, to: false` raised "names no
24
24
  # operation" for the one value most likely to be written that way
25
- # (a boolean flip). Confirmed real, live: miette's
25
+ # (a boolean flip). Confirmed real, live: an external project's
26
26
  # dream_interpretation.bluebook (`then_set :accepted, to: false`)
27
27
  # and transparency.bluebook (`then_set :always, to: false`). TODO
28
28
  # upstream via bin/evolve.
@@ -262,7 +262,7 @@ module Hecks
262
262
  # era keeps booting, which is the whole point of the rename column.
263
263
  #
264
264
  # Vendored addition, not (yet) upstream hecks: `then_set
265
- # :target, from: :source_field` (hecks_conception/miette, found
265
+ # :target, from: :source_field` (an external project, found
266
266
  # live in body/doctor/bluebook/doctor.bluebook) -- semantically
267
267
  # identical to `to:` (copy this argument/field into the target),
268
268
  # different word. TODO upstream via bin/evolve (migration plan
@@ -271,7 +271,7 @@ module Hecks
271
271
  #
272
272
  # Vendored addition, not (yet) upstream hecks (migration plan
273
273
  # task 4, i106 in-DSL math): `multiply:`/`clamp:` -- per-tick organ
274
- # math (miette's body/organs/bluebook: strength decays ×0.98,
274
+ # math (an external project's organ bluebook: strength decays ×0.98,
275
275
  # weight/strength clamp to [0, 1]), moved into the bluebook itself
276
276
  # from shell-side awk. `multiply:` mirrors
277
277
  # increment/decrement's shape exactly (a Numeric amount, applied
@@ -243,7 +243,7 @@ module Hecks
243
243
  # since ADR 0028, `command` only queues a descriptor and actually
244
244
  # builds at `#drain_pending!` time, well after this whole block
245
245
  # (including every `given` in it) has already run, so textual
246
- # order within the block no longer actually matters here; named
246
+ # order within the block does not actually matter here; named
247
247
  # for the reader anyway, since `given`'s own resolution logic
248
248
  # (`CommandBuilder#reference_named_given`) still reads whatever
249
249
  # `@named_givens` holds at the command's own build time, not by
@@ -8,7 +8,7 @@ module Hecks
8
8
  # already shipped) only checks a word's admissibility; this module
9
9
  # executes the safe, mechanical subset of what a word actually
10
10
  # does, read live off the same self-hosted grammar table — so a
11
- # builder method for one of these words no longer needs to be
11
+ # builder method for one of these words need not be
12
12
  # hand-written at all. Called from `WordGate#method_missing`'s own
13
13
  # "admitted here, no builder method for it yet" branch, so it only
14
14
  # ever sees a word whose (context, word) pair the grammar already
@@ -31,7 +31,7 @@ module Hecks
31
31
  @translates = []
32
32
  end
33
33
 
34
- # Marks THIS chapter as a bounded context — a consumer-owned chapter
34
+ # Marks this chapter as a bounded context — a consumer-owned chapter
35
35
  # that `uses_framework` / `uses_embryonaut_bluebook` will not load.
36
36
  # Framework and vendored packages get the mark automatically from
37
37
  # those words; they never write `bounded` in their own bluebooks.
@@ -158,12 +158,12 @@ module Hecks
158
158
  bluebook_ir.add_port(built)
159
159
  end
160
160
 
161
- # A TRANSLATION BOUNDARY, NOT A BUSINESS RULE — `translates "Name"
161
+ # A translation boundary, not a business rule — `translates "Name"
162
162
  # do on Foreign::Domain::SomeEvent; trigger Local.Command; end`
163
- # builds the EXACT SAME `Policy` a `policy` block inside this
163
+ # builds the exact same `Policy` a `policy` block inside this
164
164
  # domain's own `.bluebook` would (same `on_impl`/`trigger_impl`,
165
165
  # same `PolicyInterpreter` runtime — reusing `PolicyBuilder`
166
- # directly, zero new runtime semantics). What's new is only WHERE
166
+ # directly, zero new runtime semantics). What's new is only where
167
167
  # it can be written: a cross-domain reaction is a wiring/context-
168
168
  # mapping decision (this chapter conforming to a foreign chapter's
169
169
  # published event), the same kind of decision `port`/
@@ -171,23 +171,28 @@ module Hecks
171
171
  # model states about itself, which `policy` (inside the bluebook)
172
172
  # remains the right word for.
173
173
  #
174
- # MUST BE A BLOCK, not `translates Event, into: Command` — a flat
175
- # call's arguments are evaluated eagerly, under THIS builder's own
174
+ # Must be a block, not `translates Event, into: Command` — a flat
175
+ # call's arguments are evaluated eagerly, under this builder's own
176
176
  # `ConstShim` resolver (`BindingProxy.namespace`, set up by
177
- # `self.build` below), which mints a `BindingProxy` INSTANCE per
177
+ # `self.build` below), which mints a `BindingProxy` instance per
178
178
  # segment and cannot answer a further `::` (it is not a Module) —
179
179
  # a multi-segment reference like `Deploy::Tenant::TenantProvisioned`
180
180
  # would raise before this method ever ran. `port_impl`'s own
181
181
  # `ConstShim.with(->(const) { const })` swap only works because
182
182
  # its own callers never pass a multi-segment bare constant as an
183
183
  # eagerly-evaluated argument — everything of that shape lives
184
- # inside ITS block, evaluated later, under the swapped resolver.
184
+ # inside its block, evaluated later, under the swapped resolver.
185
185
  # A block defers evaluation the same way; a flat call cannot.
186
+ #
187
+ # @param name [String, Symbol] the reaction's name
188
+ # @yield the `on`/`trigger` block, evaluated later under the scoped resolver
189
+ # @return [Array<Bluebook::Policy>] the chapter's policies, with the new one appended
190
+ # @raise [Malformed] if no bluebook is registered for this domain to attach the reaction to
186
191
  def translates(name, &block)
187
192
  bluebook_ir = Hecks.current_registry.bluebook(@domain) or
188
193
  raise Malformed, "#{@domain} declares no such bluebook — translates needs one to attach its reaction to"
189
194
 
190
- # SAME RESOLVER BluebookBuilder ITSELF uses for a `policy`
195
+ # Same resolver BluebookBuilder itself uses for a `policy`
191
196
  # block's own `on`/`trigger` (bluebook_builder.rb) — a
192
197
  # `ScopedConstant`, not the bare passthrough `port_impl` swaps
193
198
  # to, because `on`/`trigger` here take genuinely multi-segment
@@ -34,7 +34,7 @@ module Hecks
34
34
  # only external facts with attribute" the refusal message
35
35
  # describes) rather than folding `to:` into identity_attribute's
36
36
  # existing Reference-attribute scan, which every operation already
37
- # in the corpus (Banking, pizzas, lifeadelics' own vendored
37
+ # in the corpus (Banking, pizzas, a client site's own vendored
38
38
  # PaymentGateway) still relies on unchanged.
39
39
  #
40
40
  # @param name [String] the operation's name
@@ -147,8 +147,8 @@ module Hecks
147
147
  .find { |rule| rule.description == description }
148
148
  end
149
149
 
150
- # **Which construct uses which primitive** — no longer a Ruby-only
151
- # Hash (that was this constant's own shape, one round ago): the
150
+ # **Which construct uses which primitive** — not a Ruby-only
151
+ # Hash, because the
152
152
  # user's own correction — "my goal is that if they read the same
153
153
  # table they behave identically" — means a table only Ruby ever
154
154
  # reads cannot deliver that, no matter how faithfully it is
@@ -172,7 +172,7 @@ module Hecks
172
172
  # after `grammar_registry` is fully built and memoized, so reads
173
173
  # the real table, every time, no exception.
174
174
  #
175
- # No longer kept in sync by hand — the same `resolves_via`/
175
+ # Not kept in sync by hand — the same `resolves_via`/
176
176
  # `disambiguator` columns, projected ahead of time into the
177
177
  # committed lib/hecks/bluebook/dsl/bootstrap_table.rb
178
178
  # (bin/project_bootstrap_table, pinned by spec/bootstrap_table_spec.rb).
@@ -268,7 +268,7 @@ module Hecks
268
268
  # Parses a whole `.translation` file into a `Translation` — the
269
269
  # domain's own `from:`/`to:` era pair, its list of `aggregate`
270
270
  # translation blocks (each built by `TranslationAggregateBuilder`
271
- # above), and any `retired` aggregates that no longer exist in the
271
+ # above), and any `retired` aggregates that do not exist in the
272
272
  # destination era.
273
273
  class TranslationBuilder
274
274
  GRAMMAR_CONTEXT = "Translation".freeze
@@ -11,8 +11,22 @@ module Hecks
11
11
  # Starts with no settings recorded.
12
12
  def initialize = @values = {}
13
13
 
14
- def method_missing(key, *args, &)
15
- @values[key.to_sym] = args.size == 1 ? args.first : args
14
+ # A call with a block records the block's own settings as a nested Hash, so a bind can
15
+ # group settings (`preview do ... end`); a call without one records its argument.
16
+ #
17
+ # @param key [Symbol] the setting's name, recorded verbatim
18
+ # @param args [Array] the setting's value: one argument is kept as is, several as an array
19
+ # @param block [Proc, nil] a nested settings block, evaluated on a fresh collector
20
+ # @return [Object] the value recorded under `key`
21
+ def method_missing(key, *args, &block)
22
+ @values[key.to_sym] =
23
+ if block
24
+ nested = SettingsCollector.new
25
+ nested.instance_eval(&block)
26
+ nested.to_h
27
+ else
28
+ args.size == 1 ? args.first : args
29
+ end
16
30
  end
17
31
 
18
32
  def respond_to_missing?(_name, _include_private = false) = true
@@ -96,6 +110,35 @@ module Hecks
96
110
  @latest = required(value, "latest version")
97
111
  end
98
112
 
113
+ # Names the connection every chapter's database-taking persistence adapter uses
114
+ # unless that chapter's own world settings name one.
115
+ #
116
+ # Answers the `default_database` word through the table's `calls:` column, the
117
+ # same way `realm_impl` does. A chapter's own
118
+ # `persisted_by("Adapter") { database ... }` still wins for that adapter.
119
+ #
120
+ # @param value [String] the connection, such as a database URL; blankness is
121
+ # judged by the world language at `build`, not here
122
+ # @return [String] the connection as stored
123
+ def default_database_impl(value)
124
+ @default_database = required(value, "default database")
125
+ end
126
+
127
+ # Names the persistence adapter every aggregate binds to unless its own chapter's
128
+ # hecksagon binds it.
129
+ #
130
+ # Answers the `default_adapter` word through the table's `calls:` column, the same
131
+ # way `realm_impl` does. Sits between an explicit bind and the framework's
132
+ # in-memory fallback; whether the adapter really is a persistence adapter is
133
+ # judged at boot, where adapters are known.
134
+ #
135
+ # @param value [String, Symbol] the adapter's declared name, such as `"PostgresEra"`;
136
+ # blankness is judged by the world language at `build`, not here
137
+ # @return [String] the adapter name as stored
138
+ def default_adapter_impl(value)
139
+ @default_adapter = required(value, "default adapter")
140
+ end
141
+
99
142
  def method_missing(verb, *args, **kwargs, &block)
100
143
  result = word_gate_dispatch(verb, args, kwargs, block)
101
144
  return result unless result.equal?(WordGate::NOT_ADMITTED)
@@ -134,7 +177,8 @@ module Hecks
134
177
  # as a blank `realm`
135
178
  def build
136
179
  MetaValidator.call_world(
137
- World.new(domain: @domain, realm: @realm, latest: @latest, settings: @settings)
180
+ World.new(domain: @domain, realm: @realm, latest: @latest, settings: @settings,
181
+ default_database: @default_database, default_adapter: @default_adapter)
138
182
  )
139
183
  end
140
184