hecks 1.3.0 → 1.5.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 (373) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/claude_code.rb +72 -7
  3. data/lib/hecks/adapters/driven/d1.rb +187 -23
  4. data/lib/hecks/adapters/driven/folder.rb +83 -10
  5. data/lib/hecks/adapters/driven/google_authentication.rb +33 -12
  6. data/lib/hecks/adapters/driven/governance_authorization.rb +87 -18
  7. data/lib/hecks/adapters/driven/heki/journal.rb +13 -4
  8. data/lib/hecks/adapters/driven/heki/saga_store.rb +56 -10
  9. data/lib/hecks/adapters/driven/heki/snapshot.rb +1 -1
  10. data/lib/hecks/adapters/driven/heki.rb +106 -9
  11. data/lib/hecks/adapters/driven/identity_registry.rb +12 -2
  12. data/lib/hecks/adapters/driven/in_memory_ordering.rb +25 -3
  13. data/lib/hecks/adapters/driven/in_process_key_vault.adapter +3 -0
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +53 -0
  15. data/lib/hecks/adapters/driven/lambda/client.rb +67 -14
  16. data/lib/hecks/adapters/driven/lambda.rb +82 -35
  17. data/lib/hecks/adapters/driven/local_storage.rb +83 -10
  18. data/lib/hecks/adapters/driven/memory.rb +205 -9
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +21 -1
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
  24. data/lib/hecks/adapters/driven/postgres.rb +175 -28
  25. data/lib/hecks/adapters/driven/prism.rb +50 -11
  26. data/lib/hecks/adapters/driven/secure_random_identity.rb +3 -0
  27. data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
  28. data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
  29. data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
  30. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
  31. data/lib/hecks/adapters/driven/sqlite.rb +181 -21
  32. data/lib/hecks/adapters/driven/system_clock.rb +3 -0
  33. data/lib/hecks/adapters/driven/tenant_provisioner.adapter +3 -0
  34. data/lib/hecks/adapters/driven/tenant_provisioner.rb +66 -0
  35. data/lib/hecks/adapters/driven.rb +6 -4
  36. data/lib/hecks/adapters/driving/github_webhook.rb +31 -18
  37. data/lib/hecks/behaviors/dsl.rb +60 -2
  38. data/lib/hecks/behaviors/expectations.rb +190 -29
  39. data/lib/hecks/behaviors/ir.rb +12 -1
  40. data/lib/hecks/behaviors/rspec.rb +9 -1
  41. data/lib/hecks/behaviors/runner.rb +21 -2
  42. data/lib/hecks/behaviors.rb +9 -1
  43. data/lib/hecks/bluebook/aggregate.rb +43 -13
  44. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +17 -10
  45. data/lib/hecks/bluebook/assembly/build.rb +26 -5
  46. data/lib/hecks/bluebook/assembly/contract.rb +98 -23
  47. data/lib/hecks/bluebook/assembly/contracts.rb +59 -52
  48. data/lib/hecks/bluebook/assembly/marks.rb +159 -30
  49. data/lib/hecks/bluebook/assembly/specializer.rb +38 -21
  50. data/lib/hecks/bluebook/assembly.rb +32 -14
  51. data/lib/hecks/bluebook/attribute.rb +26 -12
  52. data/lib/hecks/bluebook/behaviour/aggregate.rb +43 -11
  53. data/lib/hecks/bluebook/behaviour/attribute.rb +18 -5
  54. data/lib/hecks/bluebook/behaviour/chapter.rb +76 -5
  55. data/lib/hecks/bluebook/behaviour/command.rb +55 -25
  56. data/lib/hecks/bluebook/behaviour/domain_port.rb +27 -7
  57. data/lib/hecks/bluebook/behaviour/entity.rb +20 -8
  58. data/lib/hecks/bluebook/behaviour/hexagon.rb +30 -4
  59. data/lib/hecks/bluebook/behaviour/lifecycle.rb +27 -6
  60. data/lib/hecks/bluebook/behaviour/policy.rb +42 -17
  61. data/lib/hecks/bluebook/behaviour/process_manager.rb +39 -8
  62. data/lib/hecks/bluebook/behaviour/query.rb +6 -1
  63. data/lib/hecks/bluebook/behaviour/read_model.rb +29 -8
  64. data/lib/hecks/bluebook/behaviour/traits.rb +48 -12
  65. data/lib/hecks/bluebook/behaviour/value_object.rb +21 -9
  66. data/lib/hecks/bluebook/capabilities.rb +27 -0
  67. data/lib/hecks/bluebook/chapter.rb +51 -9
  68. data/lib/hecks/bluebook/command.rb +62 -17
  69. data/lib/hecks/bluebook/domain_port.rb +34 -9
  70. data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
  71. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
  72. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +282 -123
  73. data/lib/hecks/bluebook/dsl/attribute_collector.rb +112 -75
  74. data/lib/hecks/bluebook/dsl/binding_proxy.rb +81 -2
  75. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +486 -117
  76. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +179 -47
  77. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
  78. data/lib/hecks/bluebook/dsl/command_builder.rb +284 -122
  79. data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
  80. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
  81. data/lib/hecks/bluebook/dsl/entity_builder.rb +191 -61
  82. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
  83. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +130 -30
  84. data/lib/hecks/bluebook/dsl/identity_declaration.rb +38 -21
  85. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
  86. data/lib/hecks/bluebook/dsl/policy_builder.rb +86 -36
  87. data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
  88. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
  89. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +111 -47
  90. data/lib/hecks/bluebook/dsl/query_builder.rb +37 -8
  91. data/lib/hecks/bluebook/dsl/read_model_builder.rb +127 -52
  92. data/lib/hecks/bluebook/dsl/rule_reference.rb +97 -43
  93. data/lib/hecks/bluebook/dsl/translation_builder.rb +150 -44
  94. data/lib/hecks/bluebook/dsl/value_object_builder.rb +68 -20
  95. data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
  96. data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
  97. data/lib/hecks/bluebook/entity.rb +40 -11
  98. data/lib/hecks/bluebook/expression/ast_json.rb +128 -36
  99. data/lib/hecks/bluebook/expression/ast_reader.rb +32 -3
  100. data/lib/hecks/bluebook/expression/canonical_form.rb +55 -16
  101. data/lib/hecks/bluebook/expression/evaluator.rb +221 -43
  102. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +54 -18
  103. data/lib/hecks/bluebook/expression/resolver.rb +369 -128
  104. data/lib/hecks/bluebook/hexagon.rb +35 -1
  105. data/lib/hecks/bluebook/lifecycle.rb +12 -1
  106. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +2 -1
  107. data/lib/hecks/bluebook/meta_validator/judge.rb +126 -108
  108. data/lib/hecks/bluebook/meta_validator/plan.rb +81 -46
  109. data/lib/hecks/bluebook/meta_validator/port_judge.rb +3 -2
  110. data/lib/hecks/bluebook/meta_validator/readings.rb +200 -50
  111. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +68 -41
  112. data/lib/hecks/bluebook/meta_validator/shapes.rb +166 -21
  113. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +286 -46
  114. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +11 -10
  115. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -5
  116. data/lib/hecks/bluebook/meta_validator.rb +235 -139
  117. data/lib/hecks/bluebook/model_check.rb +434 -104
  118. data/lib/hecks/bluebook/pattern_subset.rb +32 -10
  119. data/lib/hecks/bluebook/policy.rb +15 -13
  120. data/lib/hecks/bluebook/process_manager.rb +27 -14
  121. data/lib/hecks/bluebook/project_discovery.rb +5 -0
  122. data/lib/hecks/bluebook/project_loader.rb +40 -0
  123. data/lib/hecks/bluebook/project_register.rb +50 -6
  124. data/lib/hecks/bluebook/query.rb +31 -4
  125. data/lib/hecks/bluebook/read_model.rb +35 -15
  126. data/lib/hecks/bluebook/reference.rb +26 -13
  127. data/lib/hecks/bluebook/smoke_test.rb +46 -23
  128. data/lib/hecks/bluebook/synthesizer.rb +46 -12
  129. data/lib/hecks/bluebook/translation.rb +34 -5
  130. data/lib/hecks/bluebook/value_object.rb +29 -11
  131. data/lib/hecks/bluebook.rb +5 -6
  132. data/lib/hecks/codemod.rb +138 -50
  133. data/lib/hecks/construct.rb +21 -7
  134. data/lib/hecks/corpus.rb +438 -0
  135. data/lib/hecks/deploy/bluebook/deploy.hecksagon +19 -0
  136. data/lib/hecks/doc/reference.rb +200 -31
  137. data/lib/hecks/embryonaut_bluebook.rb +38 -15
  138. data/lib/hecks/facade/cli_door.rb +69 -10
  139. data/lib/hecks/facade/cli_runner.rb +105 -24
  140. data/lib/hecks/facade/command_request.rb +23 -0
  141. data/lib/hecks/facade/handle.rb +155 -35
  142. data/lib/hecks/facade/json_door.rb +106 -25
  143. data/lib/hecks/facade/surface/aggregate_door.rb +50 -27
  144. data/lib/hecks/facade/surface/chapter.rb +26 -17
  145. data/lib/hecks/facade/surface.rb +16 -3
  146. data/lib/hecks/facade.rb +15 -4
  147. data/lib/hecks/forms/app.rb +46 -30
  148. data/lib/hecks/forms/command_form_renderer.rb +70 -9
  149. data/lib/hecks/forms/field_renderer.rb +142 -6
  150. data/lib/hecks/forms/field_shape.rb +183 -19
  151. data/lib/hecks/forms/html.rb +51 -7
  152. data/lib/hecks/forms/index_renderer.rb +14 -2
  153. data/lib/hecks/forms/page.rb +14 -0
  154. data/lib/hecks/forms/params.rb +120 -23
  155. data/lib/hecks/forms/port_argument.rb +14 -2
  156. data/lib/hecks/forms/query_form_renderer.rb +65 -2
  157. data/lib/hecks/forms/record_renderer.rb +60 -2
  158. data/lib/hecks/forms/record_table.rb +28 -1
  159. data/lib/hecks/forms/reference_options.rb +24 -0
  160. data/lib/hecks/forms/value_object_shape.rb +13 -3
  161. data/lib/hecks/forms.rb +24 -4
  162. data/lib/hecks/fqn.rb +59 -1
  163. data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
  164. data/lib/hecks/framework/bluebook/privacy.bluebook +155 -0
  165. data/lib/hecks/framework/oidc.json +15 -0
  166. data/lib/hecks/framework.rb +79 -25
  167. data/lib/hecks/freezer.rb +27 -11
  168. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +241 -106
  169. data/lib/hecks/fuzzing/combination_miner.rb +178 -0
  170. data/lib/hecks/fuzzing/concurrent_dispatch.rb +241 -45
  171. data/lib/hecks/fuzzing/coverage_campaign.rb +161 -0
  172. data/lib/hecks/fuzzing/differential.rb +192 -0
  173. data/lib/hecks/fuzzing/domain_generator.rb +871 -0
  174. data/lib/hecks/fuzzing/era_boundary.rb +68 -19
  175. data/lib/hecks/fuzzing/form_census.rb +121 -20
  176. data/lib/hecks/fuzzing/generated_domain_check.rb +171 -0
  177. data/lib/hecks/fuzzing/invalid_value_generator.rb +45 -6
  178. data/lib/hecks/fuzzing/isolated_boot.rb +137 -80
  179. data/lib/hecks/fuzzing/nondeterministic.rb +79 -0
  180. data/lib/hecks/fuzzing/persistence_parity.rb +111 -21
  181. data/lib/hecks/fuzzing/properties/corrections.rb +34 -9
  182. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +300 -51
  183. data/lib/hecks/fuzzing/properties/guards.rb +86 -42
  184. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +80 -32
  185. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +40 -35
  186. data/lib/hecks/fuzzing/properties/outbox.rb +70 -32
  187. data/lib/hecks/fuzzing/properties/querying.rb +82 -28
  188. data/lib/hecks/fuzzing/properties.rb +84 -51
  189. data/lib/hecks/fuzzing/qa_settings.rb +164 -0
  190. data/lib/hecks/fuzzing/replay.rb +241 -133
  191. data/lib/hecks/fuzzing/rotation_priority.rb +48 -28
  192. data/lib/hecks/fuzzing/rust_gap_manifest.rb +139 -0
  193. data/lib/hecks/fuzzing/self_consistency.rb +315 -137
  194. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +46 -40
  195. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
  196. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
  197. data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
  198. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +59 -32
  199. data/lib/hecks/fuzzing/sequence_generator.rb +158 -23
  200. data/lib/hecks/fuzzing/shrinker.rb +309 -0
  201. data/lib/hecks/fuzzing/structural_skips.rb +37 -130
  202. data/lib/hecks/fuzzing/sweep_depth.rb +12 -4
  203. data/lib/hecks/fuzzing/target_capabilities.rb +107 -29
  204. data/lib/hecks/fuzzing/value_generator.rb +110 -22
  205. data/lib/hecks/fuzzing.rb +5 -0
  206. data/lib/hecks/grammar/evolve.rb +188 -12
  207. data/lib/hecks/grammar.rb +53 -7
  208. data/lib/hecks/ir.rb +51 -20
  209. data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
  210. data/lib/hecks/language/bluebook/policy.bluebook +11 -1
  211. data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
  212. data/lib/hecks/language/hecksagon/hecksagon.bluebook +11 -0
  213. data/lib/hecks/language/oidc.json +5 -0
  214. data/lib/hecks/literal.rb +41 -9
  215. data/lib/hecks/naming.rb +112 -31
  216. data/lib/hecks/ports/access_control.rb +53 -2
  217. data/lib/hecks/ports/agent/answers.rb +83 -6
  218. data/lib/hecks/ports/agent.rb +119 -35
  219. data/lib/hecks/ports/authentication.rb +44 -4
  220. data/lib/hecks/ports/authorization.rb +50 -11
  221. data/lib/hecks/ports/clock.rb +42 -23
  222. data/lib/hecks/ports/extraction.rb +16 -0
  223. data/lib/hecks/ports/identity_assignment.rb +23 -2
  224. data/lib/hecks/ports/identity_generation.rb +17 -3
  225. data/lib/hecks/ports/identity_resolution.rb +17 -1
  226. data/lib/hecks/ports/key_vault.port +6 -0
  227. data/lib/hecks/ports/key_vault.rb +58 -0
  228. data/lib/hecks/ports/loading.rb +4 -0
  229. data/lib/hecks/ports/persistence/append_only.rb +172 -8
  230. data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
  231. data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
  232. data/lib/hecks/ports/persistence/execution.rb +4 -0
  233. data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
  234. data/lib/hecks/ports/persistence/plugin.rb +42 -4
  235. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
  236. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
  237. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
  238. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
  239. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
  242. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
  243. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
  244. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
  245. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
  246. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +34 -5
  247. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
  248. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
  249. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
  250. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
  251. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
  252. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +95 -6
  253. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
  254. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
  255. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
  256. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
  257. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
  258. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +48 -8
  259. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
  260. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
  261. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
  262. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +58 -19
  263. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +96 -5
  264. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +15 -0
  265. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +9 -1
  266. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
  267. data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
  268. data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
  269. data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
  270. data/lib/hecks/ports/persistence/state_codec.rb +319 -0
  271. data/lib/hecks/ports/persistence.rb +36 -1
  272. data/lib/hecks/ports/projection.rb +61 -7
  273. data/lib/hecks/ports/query/in_memory.rb +41 -8
  274. data/lib/hecks/ports/query/ordering.rb +21 -6
  275. data/lib/hecks/ports/query.rb +35 -0
  276. data/lib/hecks/ports.rb +1 -0
  277. data/lib/hecks/projections/bootstrap_table.rb +147 -0
  278. data/lib/hecks/projections/diagrams.rb +315 -79
  279. data/lib/hecks/projections/glossary/html.rb +91 -3
  280. data/lib/hecks/projections/glossary/markdown.rb +50 -3
  281. data/lib/hecks/projections/glossary/mermaid.rb +49 -1
  282. data/lib/hecks/projections/glossary/sections.rb +1 -1
  283. data/lib/hecks/projections/glossary/sentences.rb +110 -5
  284. data/lib/hecks/projections/glossary.rb +173 -31
  285. data/lib/hecks/projections/ir.rb +1 -1
  286. data/lib/hecks/projections/model/deviations.rb +62 -17
  287. data/lib/hecks/projections/model.rb +75 -21
  288. data/lib/hecks/projections/oidc.rb +45 -8
  289. data/lib/hecks/projections/parser_table.rb +53 -12
  290. data/lib/hecks/projections/reference.rb +15 -3
  291. data/lib/hecks/projections/rust_vocabulary.rb +646 -0
  292. data/lib/hecks/projections/shape.rb +10 -2
  293. data/lib/hecks/projections/statements.rb +69 -22
  294. data/lib/hecks/projections/vocabulary.rb +26 -9
  295. data/lib/hecks/projections.rb +5 -3
  296. data/lib/hecks/projector/cli_projector.rb +245 -37
  297. data/lib/hecks/projector/docs_projector.rb +154 -28
  298. data/lib/hecks/projector/exporter.rb +104 -29
  299. data/lib/hecks/projector/ir_projector.rb +7 -1
  300. data/lib/hecks/projector/narrate_projector.rb +144 -23
  301. data/lib/hecks/projector/target.rb +42 -18
  302. data/lib/hecks/projector.rb +86 -18
  303. data/lib/hecks/query_ir.rb +94 -47
  304. data/lib/hecks/query_specification/common/comparators.rb +19 -3
  305. data/lib/hecks/query_specification/common/comparison.rb +109 -27
  306. data/lib/hecks/query_specification/common/dsl.rb +65 -9
  307. data/lib/hecks/query_specification/common/null_policy.rb +61 -15
  308. data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
  309. data/lib/hecks/query_specification/common/options.rb +25 -0
  310. data/lib/hecks/query_specification/field_path.rb +69 -15
  311. data/lib/hecks/query_specification/hop_path.rb +57 -20
  312. data/lib/hecks/query_specification/read_model/specification.rb +4 -0
  313. data/lib/hecks/rendering.rb +9 -3
  314. data/lib/hecks/router/namespace_installer.rb +16 -3
  315. data/lib/hecks/router.rb +56 -1
  316. data/lib/hecks/runtime/aggregate_lock.rb +20 -11
  317. data/lib/hecks/runtime/boot_gates.rb +21 -3
  318. data/lib/hecks/runtime/caller.rb +40 -8
  319. data/lib/hecks/runtime/capability_graph.rb +13 -2
  320. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +40 -41
  321. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +45 -67
  322. data/lib/hecks/runtime/command_interpreter.rb +195 -113
  323. data/lib/hecks/runtime/command_rules/admissibility.rb +231 -80
  324. data/lib/hecks/runtime/command_rules/arithmetic.rb +154 -96
  325. data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
  326. data/lib/hecks/runtime/command_rules/emission.rb +18 -1
  327. data/lib/hecks/runtime/command_rules/references.rb +145 -55
  328. data/lib/hecks/runtime/command_rules.rb +3 -0
  329. data/lib/hecks/runtime/dependency_planning.rb +56 -11
  330. data/lib/hecks/runtime/dispatcher.rb +263 -92
  331. data/lib/hecks/runtime/entity_element.rb +304 -67
  332. data/lib/hecks/runtime/entity_interpreter.rb +149 -88
  333. data/lib/hecks/runtime/errors.rb +37 -23
  334. data/lib/hecks/runtime/event.rb +15 -10
  335. data/lib/hecks/runtime/identity.rb +91 -23
  336. data/lib/hecks/runtime/instance.rb +103 -18
  337. data/lib/hecks/runtime/interpreting.rb +24 -16
  338. data/lib/hecks/runtime/invocation.rb +358 -0
  339. data/lib/hecks/runtime/loader.rb +105 -19
  340. data/lib/hecks/runtime/outbox.rb +164 -26
  341. data/lib/hecks/runtime/policy_interpreter.rb +73 -60
  342. data/lib/hecks/runtime/port_operation_interpreter.rb +42 -19
  343. data/lib/hecks/runtime/query_interpreter.rb +93 -74
  344. data/lib/hecks/runtime/reaction_invocation.rb +73 -28
  345. data/lib/hecks/runtime/read_model_interpreter.rb +60 -44
  346. data/lib/hecks/runtime/rebuild_sweep.rb +32 -4
  347. data/lib/hecks/runtime/reference_hop.rb +48 -6
  348. data/lib/hecks/runtime/refusal_wording.rb +142 -115
  349. data/lib/hecks/runtime/registry/saga_persistence.rb +32 -21
  350. data/lib/hecks/runtime/registry/verification.rb +153 -28
  351. data/lib/hecks/runtime/registry.rb +202 -32
  352. data/lib/hecks/runtime/remote_dispatcher.rb +125 -24
  353. data/lib/hecks/runtime/routing.rb +36 -154
  354. data/lib/hecks/runtime/saga_interpreter/correlation.rb +25 -27
  355. data/lib/hecks/runtime/saga_interpreter.rb +90 -76
  356. data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
  357. data/lib/hecks/runtime/tenant_check.rb +33 -13
  358. data/lib/hecks/runtime/tenant_scope.rb +23 -5
  359. data/lib/hecks/runtime/value/admission.rb +75 -30
  360. data/lib/hecks/runtime/value/coercion.rb +555 -142
  361. data/lib/hecks/runtime/value/entity_list_coercion.rb +132 -60
  362. data/lib/hecks/runtime/value.rb +71 -21
  363. data/lib/hecks/runtime.rb +39 -7
  364. data/lib/hecks/storehouse.rb +368 -72
  365. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +130 -0
  366. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +32 -0
  367. data/lib/hecks/version.rb +3 -3
  368. data/lib/hecks/vocabulary.rb +205 -4
  369. data/lib/hecks.rb +91 -11
  370. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +19 -11
  371. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +24 -12
  372. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +38 -14
  373. metadata +28 -2
@@ -6,8 +6,8 @@ require_relative "../../runtime/instance"
6
6
 
7
7
  module Hecks
8
8
  module Adapters
9
- # THE READ-SIDE HALF OF LAMBDA ROUTING — `persisted_by("Lambda")`'s
10
- # own adapter, resolved through the SAME `Ports::Persistence`
9
+ # **The read-side half of lambda routing** — `persisted_by("Lambda")`'s
10
+ # own adapter, resolved through the same `Ports::Persistence`
11
11
  # machinery `persisted_by("Postgres")`/`persisted_by("Memory")`
12
12
  # already use (`Runtime::Registry#repository`, `RepositoryFactory
13
13
  # .build`) — no new framework plumbing, just a new adapter class at
@@ -16,7 +16,7 @@ module Hecks
16
16
  # compose through one shared `Client` per domain rather than each
17
17
  # inventing its own AWS wiring.
18
18
  #
19
- # READ-ONLY, DELIBERATELY — `append`/`project` raise rather than
19
+ # **Read-only, deliberately** — `append`/`project` raise rather than
20
20
  # silently no-op. A write reaching this class would mean
21
21
  # `Runtime::CommandInterpreter` ran locally against a Lambda-routed
22
22
  # domain, which is exactly the bypass `Runtime::RemoteDispatcher`
@@ -29,6 +29,16 @@ module Hecks
29
29
 
30
30
  attr_reader :aggregate
31
31
 
32
+ # Resolves which Lambda function's Store to read from and builds the client that
33
+ # reads it.
34
+ #
35
+ # @param aggregate [Bluebook::Aggregate] the aggregate whose records this adapter reads
36
+ # @param settings [Hash{Symbol, String => Object}] world settings for the binding:
37
+ # `domain` (prefixes the instances lookup; default the aggregate's own name),
38
+ # `region` (default `"us-east-1"`) and `function` (the function name, when it is not
39
+ # `hecks-<domain>`), each read under a Symbol or a String key
40
+ # @param root [String, nil] the boot's own project directory, used with `DOMAIN_NAME`
41
+ # to resolve which function to call; nil falls further back to `domain`
32
42
  def initialize(aggregate:, settings: {}, root: nil)
33
43
  @aggregate = aggregate
34
44
  domain =
@@ -39,59 +49,81 @@ module Hecks
39
49
  else
40
50
  aggregate.name
41
51
  end
42
- region =
43
- if settings.key?(:region)
44
- settings[:region]
45
- elsif settings.key?("region")
46
- settings["region"]
47
- else
48
- "us-east-1"
49
- end
50
- # TWO DIFFERENT "domain"s, deliberately not conflated: `domain`
51
- # (this aggregate's OWN bluebook name — "Identity", "Governance")
52
+ region = setting(settings, :region, "us-east-1")
53
+ # Named, when this deployment's function isn't `hecks-<domain>`
54
+ # — `Client`'s own comment has the real case that needs it.
55
+ # Absent (every domain whose stack name was never pinned), the
56
+ # computation below is exactly as it was.
57
+ function = setting(settings, :function, nil)
58
+ # Two different "domain"s, deliberately not conflated: `domain`
59
+ # (this aggregate's own bluebook name — "Identity", "Governance")
52
60
  # only ever prefixes the instances lookup, since that's how
53
61
  # rust/host's own `Store::instances()` keys every record
54
62
  # (`registry.rb`'s own `"#{a[:domain_name]}::#{a[:name]}#"`
55
63
  # dump format, unchanged by which chapter attached it). The
56
- # FUNCTION to actually call is a different question: Governance
57
- # and Identity aggregates are compiled into the ATTACHING
64
+ # function to actually call is a different question: Governance
65
+ # and Identity aggregates are compiled into the attaching
58
66
  # domain's own Lambda (one merged `Store` per target — Phase 0's
59
67
  # framework-bluebook work), never a function of their own, so
60
68
  # `settings[:domain]` is the wrong signal for `Client.new`.
61
69
  # `root` is the boot's own directory (`Registry#root`, shared by
62
- # EVERY bluebook in one registry regardless of which one
70
+ # every bluebook in one registry regardless of which one
63
71
  # attached it) — `File.basename(root)` reproduces the exact
64
72
  # same string `bin/project_deploy`'s own `stack_name` computes
65
- # from the domain PATH, so the two can never name two
66
- # different functions for the same deploy... on a LOCAL boot,
73
+ # from the domain path, so the two can never name two
74
+ # different functions for the same deploy... on a local boot,
67
75
  # where `root` is a real project directory. Inside the deployed
68
- # Lambda itself `root` is ALWAYS `/var/task` (every Lambda's own
76
+ # Lambda itself `root` is always `/var/task` (every Lambda's own
69
77
  # fixed code root, regardless of domain) — `File.basename` gives
70
78
  # "task", not the domain name, and invokes the wrong function
71
79
  # entirely. A real, live AccessDeniedException on
72
80
  # "hecks-task" caught this: invisible through every earlier
73
81
  # phase's own verify step, all run from a local boot, until
74
- # WebFunction became the first Ruby process to EVER make this
82
+ # WebFunction became the first Ruby process to ever make this
75
83
  # exact call from inside a deployed Lambda. `DOMAIN_NAME` (set
76
84
  # by bin/project_deploy's own WebFunction Environment) is the
77
85
  # real, unambiguous signal in that specific context; the
78
86
  # root-basename heuristic stays as the local-boot fallback,
79
87
  # unchanged.
80
88
  function_domain = ENV["DOMAIN_NAME"] || (root ? File.basename(root) : domain)
81
- @client = Client.new(domain: function_domain, region: region)
89
+ @client = Client.new(domain: function_domain, region: region, function: function)
82
90
  @prefix = "#{domain}::#{aggregate.hecks_name}#"
83
91
  end
84
92
 
93
+ # Looks up the current record for one aggregate identity, reading the Lambda's own
94
+ # Store fresh on every call.
95
+ #
96
+ # @param id [String, Object] the aggregate identity, compared as `id.to_s`
97
+ # @return [Runtime::Instance, nil] the decoded record, or nil when no record has that id
85
98
  def find(id)
86
99
  instances[id.to_s]
87
100
  end
88
101
 
102
+ # Lists every stored record, in id order unless an ordering attribute is given.
103
+ #
104
+ # @param order_by [String, Symbol, nil] attribute (or dotted value-object path) to sort
105
+ # by; nil orders by id alone
106
+ # @param direction [Symbol, String] `:asc` or `:desc`
107
+ # @return [Array<Runtime::Instance>] the decoded records, `[]` when the Store holds none
108
+ # with this aggregate's own prefix
109
+ # @raise [Runtime::WiringError] if `order_by` names no attribute of the aggregate
89
110
  def all(order_by: nil, direction: :asc)
90
111
  InMemoryOrdering.ordered(instances.values, aggregate: @aggregate, order_by: order_by, direction: direction)
91
112
  end
92
113
 
114
+ # Counts the records currently held for this aggregate.
115
+ #
116
+ # @return [Integer] number of records
93
117
  def count = instances.size
94
118
 
119
+ # Answers a declared query by filtering, ordering and paging the held records in Ruby.
120
+ #
121
+ # @param specification [QuerySpecification::Common::Options] the declared query
122
+ # @param args [Hash{Symbol => Object}] values for the specification's symbolic operands
123
+ # @param context [Hash] execution context from `Ports::Query.execute`; accepted for the
124
+ # port's call shape and not read
125
+ # @return [Array<Runtime::Instance>] the matching records, `[]` when none match
126
+ # @raise [Runtime::WiringError] if a where clause uses an operation no comparator handles
95
127
  def query(specification, args = {}, context: {})
96
128
  Ports::Query::InMemory.execute(instances.values, specification, args)
97
129
  end
@@ -105,18 +137,36 @@ module Hecks
105
137
  # 1 — there is no local write-ahead log for `recover!` to replay),
106
138
  # `append`/`project` raise rather than silently no-op.
107
139
 
140
+ # Reads a world setting under either a Symbol or a String key, with a fallback.
141
+ #
142
+ # A `.world` block's settings arrive symbol-keyed from the DSL and
143
+ # string-keyed from a round-tripped export, so every read has to
144
+ # accept both — one helper rather than the same five lines per
145
+ # key.
146
+ #
147
+ # @param settings [Hash] the world settings Hash to read from
148
+ # @param key [Symbol] the setting name, tried as itself and as `key.to_s`
149
+ # @param fallback [Object] the value to return when neither key is present
150
+ # @return [Object] the setting's value, or `fallback` when absent
151
+ def setting(settings, key, fallback)
152
+ return settings[key] if settings.key?(key)
153
+ return settings[key.to_s] if settings.key?(key.to_s)
154
+
155
+ fallback
156
+ end
157
+
108
158
  private
109
159
 
110
- # RE-FETCHED EVERY CALL, deliberately NOT memoized across them —
160
+ # Re-fetched every call, deliberately not memoized across them —
111
161
  # this adapter itself is long-lived (one instance per aggregate,
112
- # held by the registry `RUNTIME = Hecks.boot(...)` builds ONCE
162
+ # held by the registry `RUNTIME = Hecks.boot(...)` builds once
113
163
  # per Lambda web process — WebFunction's own top-level constant,
114
164
  # reused warm across every HTTP request that process serves, not
115
- # rebuilt per request the way a memoize-for-one-request comment
116
- # here used to assume). A real, live bug caught this: a mutation
165
+ # rebuilt per request the way memoizing here would wrongly assume).
166
+ # A real, live bug caught this: a mutation
117
167
  # dispatched fine (RemoteDispatcher always calls the dispatch
118
- # Lambda fresh) and the very next `.all` on the SAME warm
119
- # container kept returning the state from BEFORE that mutation,
168
+ # Lambda fresh) and the very next `.all` on the same warm
169
+ # container kept returning the state from before that mutation,
120
170
  # forever, until the container cold-started — memoizing here
121
171
  # made every write invisible to every read on a warm container.
122
172
  # Keyed by bare id (the part after "Domain::Aggregate#"), not the
@@ -130,15 +180,12 @@ module Hecks
130
180
  end.to_h
131
181
  end
132
182
 
133
- # Lambda's own JSON response is already Ruby-decoded with STRING
134
- # keys (plain `JSON.parse`, no `symbolize_names:`) — every other
135
- # adapter's own `instance(row)` builder (Postgres, Sqlite) hands
136
- # `Runtime::Instance.new` a SYMBOL-keyed state hash instead. A
137
- # round trip through `JSON.generate`/`JSON.parse` is simpler and
138
- # safer than a hand-rolled deep-symbolize helper for what is not
139
- # a hot path.
183
+ # Lambda's own JSON response is already Ruby-decoded with string
184
+ # keys (plain `JSON.parse`, no `symbolize_names:`) — decoded through
185
+ # the state codec (PR A3), the same IR-driven spelling every other
186
+ # adapter's read produces.
140
187
  def build_instance(id, state)
141
- Runtime::Instance.new(aggregate: @aggregate, id: id, state: JSON.parse(JSON.generate(state), symbolize_names: true))
188
+ Runtime::Instance.new(aggregate: @aggregate, id: id, state: Ports::Persistence::StateCodec.decode(@aggregate, state))
142
189
  end
143
190
  end
144
191
  end
@@ -5,13 +5,13 @@ require_relative "../../runtime/instance"
5
5
 
6
6
  module Hecks
7
7
  module Adapters
8
- # A BROWSER-HOSTED DOMAIN'S OWN DECLARED INTENT — not a second Memory
8
+ # **A browser-hosted domain's own declared intent** — not a second Memory
9
9
  # wearing a different name. Ruby has no way to reach a real browser's
10
10
  # `window.localStorage` at all (it is per-tab, per-origin, JS-only,
11
11
  # unreachable over any network the way D1's own REST API is) — so
12
12
  # this Ruby-side adapter is honestly a stand-in: in-process, ephemeral,
13
13
  # mechanically identical to Memory. What earns it a name of its own
14
- # is what it DECLARES, not what it happens to do in Ruby: `persisted_by
14
+ # is what it declares, not what it happens to do in Ruby: `persisted_by
15
15
  # "LocalStorage"` says "this domain expects real, durable, single-
16
16
  # device storage the moment it's actually running where it's meant to
17
17
  # run" — the same distinction Heki (real local durability) already
@@ -20,26 +20,35 @@ module Hecks
20
20
  # model_check` all get a domain that boots and behaves correctly
21
21
  # against this adapter; only a real browser gets the real durability.
22
22
  #
23
- # THE REAL BROWSER HALF lives outside this file entirely: `rust/web`'s
23
+ # The real browser half lives outside this file entirely: `rust/web`'s
24
24
  # `dispatch(json)` (docs/implemented/decisions/0015) takes an optional
25
25
  # `"seed"` (the exact `"instances"` shape it also answers with) plus
26
26
  # `"steps"` — a host rehydrates from a prior snapshot and replays only
27
27
  # the new command(s), rather than the whole history every call. A
28
28
  # page bound to this adapter is expected to hold that snapshot in
29
29
  # `window.localStorage` itself (get on load, set after every
30
- # `dispatch`) — the seed/instances round trip IS the adapter, once
30
+ # `dispatch`) — the seed/instances round trip is the adapter, once
31
31
  # you're in the one runtime that can actually reach the storage this
32
32
  # name promises.
33
33
  class LocalStorage
34
- # TENANT-CAPABLE TRIVIALLY, same reasoning as Memory's own — a
34
+ # Tenant-capable trivially, same reasoning as Memory's own — a
35
35
  # browser tab is exactly one origin, exactly one user; there is no
36
36
  # second tenant this in-process Hash could ever confuse a first
37
37
  # one with.
38
+ #
39
+ # @return [Boolean] true, always
38
40
  def self.tenant_capable? = true
41
+
42
+ # Lists the optional persistence behaviours this adapter advertises.
43
+ #
44
+ # @return [Array<Symbol>] `[:atomic_put]`
39
45
  def persistence_capabilities = [:atomic_put]
40
46
 
41
47
  attr_reader :aggregate, :events
42
48
 
49
+ # @param aggregate [Bluebook::Aggregate] the aggregate this store persists
50
+ # @param settings [Hash] accepted but not read by this class
51
+ # @param root [String, nil] accepted but not read by this class
43
52
  def initialize(aggregate:, settings: {}, root: nil)
44
53
  @aggregate = aggregate
45
54
  @records = {}
@@ -47,40 +56,86 @@ module Hecks
47
56
  @entries = []
48
57
  end
49
58
 
59
+ # Reads one record's current projected state.
60
+ #
61
+ # @param id [String, Object] the record's identity, compared as `id.to_s`
62
+ # @return [Runtime::Instance, nil] the stored record, or nil when no record has that id
50
63
  def find(id) = @records[id.to_s]
64
+
65
+ # Counts the records currently projected.
66
+ #
67
+ # @return [Integer] number of stored records
51
68
  def count = @records.size
52
69
 
70
+ # Lists every record currently projected.
71
+ #
72
+ # @param order_by [String, Symbol, nil] an attribute name to sort by; nil keeps
73
+ # insertion order
74
+ # @param direction [Symbol] `:asc` or `:desc`
75
+ # @return [Array<Runtime::Instance>] the stored records; `[]` when there are none
53
76
  def all(order_by: nil, direction: :asc)
54
77
  InMemoryOrdering.ordered(@records.values, aggregate: @aggregate, order_by: order_by, direction: direction)
55
78
  end
56
79
 
57
- # THE DECISION THE GUIDE ASKS FOR, MADE EXPLICITLY: no compiled
80
+ # Answers a declared query specification against the projected records.
81
+ #
82
+ # The decision the guide asks for, made explicitly: no compiled
58
83
  # dialect of its own, same as Heki/Memory — a personal-scale local
59
84
  # store answering by walking `all` is correct on day one, and
60
85
  # nothing about a browser tab's own data volume asks for pushdown.
86
+ #
87
+ # @param specification [QuerySpecification::Common::Options,
88
+ # Bluebook::Behaviour::ReadModel::FilteredOptions] the declared query specification
89
+ # @param args [Hash{Symbol => Object}] bound values for the specification's placeholders
90
+ # @param context [Hash{Symbol => Object}] call context; `:registry` is read and passed
91
+ # through for registry-aware comparisons
92
+ # @return [Array<Runtime::Instance>] the matching records, ordered and paged
61
93
  def query(specification, args = {}, context: {})
62
94
  Ports::Query::InMemory.execute(all, specification, args, registry: context[:registry])
63
95
  end
64
96
 
97
+ # Records one journal entry, holding a codec copy of its state, the same as `Memory#append`.
98
+ #
99
+ # @param entry [Ports::Persistence::Entry] the save or delete to journal
100
+ # @return [Ports::Persistence::Entry] the caller's own `entry`, not the journalled copy
65
101
  def append(entry)
66
- @entries << entry
102
+ copied = Ports::Persistence::Entry.new(operation: entry.operation, id: entry.id,
103
+ state: copy(entry.state), mirrors: entry.mirrors)
104
+ @entries << copied
67
105
  entry
68
106
  end
69
107
 
108
+ # Applies one journaled entry to the current-state store.
109
+ #
110
+ # @param entry [Persistence::Entry] the save or delete to materialize
111
+ # @return [Runtime::Instance, nil] on a save, the newly stored record; on a delete, the
112
+ # removed record, or nil when no record had that id
70
113
  def project(entry)
71
114
  if entry.save?
72
- @records[entry.id] = Runtime::Instance.new(aggregate: @aggregate, id: entry.id, state: entry.state.dup)
115
+ @records[entry.id] = Runtime::Instance.new(aggregate: @aggregate, id: entry.id, state: copy(entry.state))
73
116
  else
74
117
  @records.delete(entry.id)
75
118
  end
76
119
  end
77
120
 
121
+ # Journals and projects an instance's state.
122
+ #
123
+ # @param instance [Runtime::Instance] the record to persist
124
+ # @return [Runtime::Instance] the newly stored record (a copy of `instance`'s state)
78
125
  def save(instance)
79
- entry = Ports::Persistence::Entry.new(operation: "save", id: instance.id.to_s, state: instance.state.dup)
126
+ entry = Ports::Persistence::Entry.new(operation: "save", id: instance.id.to_s, state: copy(instance.state))
80
127
  append(entry)
81
128
  project(entry)
82
129
  end
83
130
 
131
+ # Writes an entry through an existence check, refusing to replace an existing record
132
+ # when asked.
133
+ #
134
+ # @param entry [Persistence::Entry] the entry to persist (its `id` checked for an
135
+ # existing record)
136
+ # @param insert_only [Boolean] true to refuse replacing a record that already exists
137
+ # @return [Symbol] `:conflicted` when `insert_only` met an existing record and nothing
138
+ # was written; `:inserted` or `:replaced` otherwise
84
139
  def atomic_put(entry, insert_only: false)
85
140
  exists = @records.key?(entry.id.to_s)
86
141
  return :conflicted if insert_only && exists
@@ -91,16 +146,30 @@ module Hecks
91
146
  status
92
147
  end
93
148
 
149
+ # Journals and projects the removal of one record.
150
+ #
151
+ # @param id [String, Object] the record's identity, compared as `id.to_s`
152
+ # @return [Runtime::Instance, nil] the removed record, or nil when no record had that id
94
153
  def delete(id)
95
154
  entry = Ports::Persistence::Entry.new(operation: "delete", id: id.to_s, state: nil)
96
155
  append(entry)
97
156
  project(entry)
98
157
  end
99
158
 
159
+ # Records one emitted event in this adapter's in-memory event log.
160
+ #
161
+ # @param event [Runtime::Event] the event to record
162
+ # @return [Array<Runtime::Event>] the adapter's in-memory event log, including `event`
100
163
  def record_event(event) = @events << event
101
164
 
165
+ # Reads the whole journal, oldest entry first.
166
+ #
167
+ # @return [Array<Persistence::Entry>] a shallow copy of every appended entry
102
168
  def entries = @entries.dup
103
169
 
170
+ # Clears the stored records, events and journal so a kept runtime starts clean.
171
+ #
172
+ # @return [LocalStorage] self, so a caller can chain after resetting
104
173
  def reset!
105
174
  @records = {}
106
175
  @events = []
@@ -108,7 +177,11 @@ module Hecks
108
177
  self
109
178
  end
110
179
 
111
- # NOT lineage_capable? — deliberately absent, the same trade Heki
180
+ private
181
+
182
+ def copy(state) = Ports::Persistence::StateCodec.copy(@aggregate, state)
183
+
184
+ # Not lineage_capable? — deliberately absent, the same trade Heki
112
185
  # makes and states plainly (writing-an-adapter.md's own section on
113
186
  # it): a domain bound here has no edge for its own shape to travel
114
187
  # across if it ever changes; that must be hand-migrated, or the