hecks 0.2.0 → 0.3.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 (408) hide show
  1. checksums.yaml +5 -5
  2. data/lib/hecks/adapters/driven/claude_code.adapter +3 -0
  3. data/lib/hecks/adapters/driven/claude_code.rb +127 -0
  4. data/lib/hecks/adapters/driven/d1.adapter +12 -0
  5. data/lib/hecks/adapters/driven/d1.rb +403 -0
  6. data/lib/hecks/adapters/driven/folder.adapter +3 -0
  7. data/lib/hecks/adapters/driven/folder.rb +199 -0
  8. data/lib/hecks/adapters/driven/google_authentication.adapter +3 -0
  9. data/lib/hecks/adapters/driven/google_authentication.rb +100 -0
  10. data/lib/hecks/adapters/driven/governance_authorization.adapter +3 -0
  11. data/lib/hecks/adapters/driven/governance_authorization.rb +62 -0
  12. data/lib/hecks/adapters/driven/heki/journal.rb +51 -0
  13. data/lib/hecks/adapters/driven/heki/saga_store.rb +0 -0
  14. data/lib/hecks/adapters/driven/heki/snapshot.rb +38 -0
  15. data/lib/hecks/adapters/driven/heki.adapter +4 -0
  16. data/lib/hecks/adapters/driven/heki.rb +148 -0
  17. data/lib/hecks/adapters/driven/identity_registry.adapter +3 -0
  18. data/lib/hecks/adapters/driven/identity_registry.rb +26 -0
  19. data/lib/hecks/adapters/driven/in_memory_ordering.rb +51 -0
  20. data/lib/hecks/adapters/driven/lambda/client.rb +63 -0
  21. data/lib/hecks/adapters/driven/lambda.adapter +4 -0
  22. data/lib/hecks/adapters/driven/lambda.rb +131 -0
  23. data/lib/hecks/adapters/driven/memory.adapter +3 -0
  24. data/lib/hecks/adapters/driven/memory.rb +103 -0
  25. data/lib/hecks/adapters/driven/mock_stripe_adapter.adapter +3 -0
  26. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +28 -0
  27. data/lib/hecks/adapters/driven/postgres/codec.rb +80 -0
  28. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +168 -0
  29. data/lib/hecks/adapters/driven/postgres.adapter +5 -0
  30. data/lib/hecks/adapters/driven/postgres.rb +391 -0
  31. data/lib/hecks/adapters/driven/postgres_era/lineage/era_store.rb +171 -0
  32. data/lib/hecks/adapters/driven/postgres_era/lineage/field_cache.rb +190 -0
  33. data/lib/hecks/adapters/driven/postgres_era/lineage/head_compiler.rb +429 -0
  34. data/lib/hecks/adapters/driven/postgres_era/lineage/mint_transaction.rb +166 -0
  35. data/lib/hecks/adapters/driven/postgres_era/lineage/provisioning.rb +286 -0
  36. data/lib/hecks/adapters/driven/postgres_era/lineage/resumable_backfill.rb +168 -0
  37. data/lib/hecks/adapters/driven/postgres_era/lineage/tail_merge.rb +163 -0
  38. data/lib/hecks/adapters/driven/postgres_era/lineage/transform_installer.rb +114 -0
  39. data/lib/hecks/adapters/driven/postgres_era/lineage.rb +137 -0
  40. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/coverage_check.rb +89 -0
  41. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/era_resolver.rb +82 -0
  42. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/merge_coordinator.rb +43 -0
  43. data/lib/hecks/adapters/driven/postgres_era/lineage_manager/minter.rb +132 -0
  44. data/lib/hecks/adapters/driven/postgres_era/lineage_manager.rb +74 -0
  45. data/lib/hecks/adapters/driven/postgres_era.adapter +6 -0
  46. data/lib/hecks/adapters/driven/postgres_era.rb +671 -0
  47. data/lib/hecks/adapters/driven/prism.adapter +3 -0
  48. data/lib/hecks/adapters/driven/prism.rb +80 -0
  49. data/lib/hecks/adapters/driven/secure_random_identity.adapter +3 -0
  50. data/lib/hecks/adapters/driven/secure_random_identity.rb +14 -0
  51. data/lib/hecks/adapters/driven/sql_query_builder.rb +221 -0
  52. data/lib/hecks/adapters/driven/sqlite/codec.rb +63 -0
  53. data/lib/hecks/adapters/driven/sqlite/projection.rb +105 -0
  54. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +180 -0
  55. data/lib/hecks/adapters/driven/sqlite.adapter +9 -0
  56. data/lib/hecks/adapters/driven/sqlite.rb +285 -0
  57. data/lib/hecks/adapters/driven/system_clock.adapter +3 -0
  58. data/lib/hecks/adapters/driven/system_clock.rb +14 -0
  59. data/lib/hecks/adapters/driven.rb +36 -0
  60. data/lib/hecks/adapters.rb +6 -0
  61. data/lib/hecks/behaviors/dsl.rb +96 -0
  62. data/lib/hecks/behaviors/expectations.rb +280 -0
  63. data/lib/hecks/behaviors/ir.rb +31 -0
  64. data/lib/hecks/behaviors/rspec.rb +42 -0
  65. data/lib/hecks/behaviors/runner.rb +96 -0
  66. data/lib/hecks/behaviors.rb +25 -0
  67. data/lib/hecks/bluebook/aggregate.rb +108 -0
  68. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +134 -0
  69. data/lib/hecks/bluebook/assembly/build.rb +48 -0
  70. data/lib/hecks/bluebook/assembly/contract.rb +112 -0
  71. data/lib/hecks/bluebook/assembly/contracts.rb +409 -0
  72. data/lib/hecks/bluebook/assembly/marks.rb +227 -0
  73. data/lib/hecks/bluebook/assembly/specializer.rb +70 -0
  74. data/lib/hecks/bluebook/assembly.rb +78 -0
  75. data/lib/hecks/bluebook/attribute.rb +96 -0
  76. data/lib/hecks/bluebook/behaviour/aggregate.rb +83 -0
  77. data/lib/hecks/bluebook/behaviour/attribute.rb +27 -0
  78. data/lib/hecks/bluebook/behaviour/chapter.rb +72 -0
  79. data/lib/hecks/bluebook/behaviour/command.rb +116 -0
  80. data/lib/hecks/bluebook/behaviour/domain_port.rb +25 -0
  81. data/lib/hecks/bluebook/behaviour/entity.rb +59 -0
  82. data/lib/hecks/bluebook/behaviour/hexagon.rb +50 -0
  83. data/lib/hecks/bluebook/behaviour/lifecycle.rb +51 -0
  84. data/lib/hecks/bluebook/behaviour/policy.rb +52 -0
  85. data/lib/hecks/bluebook/behaviour/process_manager.rb +38 -0
  86. data/lib/hecks/bluebook/behaviour/query.rb +10 -0
  87. data/lib/hecks/bluebook/behaviour/read_model.rb +29 -0
  88. data/lib/hecks/bluebook/behaviour/traits.rb +81 -0
  89. data/lib/hecks/bluebook/behaviour/value_object.rb +33 -0
  90. data/lib/hecks/bluebook/chapter.rb +68 -0
  91. data/lib/hecks/bluebook/command.rb +124 -0
  92. data/lib/hecks/bluebook/domain_port.rb +102 -0
  93. data/lib/hecks/bluebook/dsl/adapter_builder.rb +34 -0
  94. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +906 -0
  95. data/lib/hecks/bluebook/dsl/attribute_collector.rb +327 -0
  96. data/lib/hecks/bluebook/dsl/binding_proxy.rb +71 -0
  97. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +1018 -0
  98. data/lib/hecks/bluebook/dsl/command_builder.rb +626 -0
  99. data/lib/hecks/bluebook/dsl/const_shim.rb +81 -0
  100. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +79 -0
  101. data/lib/hecks/bluebook/dsl/entity_builder.rb +305 -0
  102. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +366 -0
  103. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +163 -0
  104. data/lib/hecks/bluebook/dsl/identity_declaration.rb +191 -0
  105. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +44 -0
  106. data/lib/hecks/bluebook/dsl/malformed.rb +7 -0
  107. data/lib/hecks/bluebook/dsl/policy_builder.rb +120 -0
  108. data/lib/hecks/bluebook/dsl/port_builder.rb +30 -0
  109. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +142 -0
  110. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +207 -0
  111. data/lib/hecks/bluebook/dsl/query_builder.rb +113 -0
  112. data/lib/hecks/bluebook/dsl/read_model_builder.rb +233 -0
  113. data/lib/hecks/bluebook/dsl/rule_reference.rb +172 -0
  114. data/lib/hecks/bluebook/dsl/translation_builder.rb +243 -0
  115. data/lib/hecks/bluebook/dsl/value_object_builder.rb +178 -0
  116. data/lib/hecks/bluebook/dsl/word_gate.rb +221 -0
  117. data/lib/hecks/bluebook/dsl/world_builder.rb +77 -0
  118. data/lib/hecks/bluebook/dsl.rb +45 -0
  119. data/lib/hecks/bluebook/entity.rb +103 -0
  120. data/lib/hecks/bluebook/expression/canonical_form.rb +55 -0
  121. data/lib/hecks/bluebook/expression/evaluator.rb +261 -0
  122. data/lib/hecks/bluebook/expression/projection.json +170 -0
  123. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +233 -0
  124. data/lib/hecks/bluebook/expression/resolver.rb +630 -0
  125. data/lib/hecks/bluebook/expression.rb +13 -0
  126. data/lib/hecks/bluebook/hexagon.rb +60 -0
  127. data/lib/hecks/bluebook/lifecycle.rb +42 -0
  128. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +54 -0
  129. data/lib/hecks/bluebook/meta_validator/judge.rb +559 -0
  130. data/lib/hecks/bluebook/meta_validator/plan.rb +332 -0
  131. data/lib/hecks/bluebook/meta_validator/port_judge.rb +47 -0
  132. data/lib/hecks/bluebook/meta_validator/readings.rb +350 -0
  133. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +312 -0
  134. data/lib/hecks/bluebook/meta_validator/shapes.rb +246 -0
  135. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +255 -0
  136. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +138 -0
  137. data/lib/hecks/bluebook/meta_validator/world_judge.rb +78 -0
  138. data/lib/hecks/bluebook/meta_validator.rb +452 -0
  139. data/lib/hecks/bluebook/model_check.rb +318 -0
  140. data/lib/hecks/bluebook/pattern_subset.rb +120 -0
  141. data/lib/hecks/bluebook/policy.rb +41 -0
  142. data/lib/hecks/bluebook/process_manager.rb +86 -0
  143. data/lib/hecks/bluebook/project_discovery.rb +30 -0
  144. data/lib/hecks/bluebook/project_loader.rb +40 -0
  145. data/lib/hecks/bluebook/project_register.rb +82 -0
  146. data/lib/hecks/bluebook/query.rb +61 -0
  147. data/lib/hecks/bluebook/read_model.rb +109 -0
  148. data/lib/hecks/bluebook/reference.rb +74 -0
  149. data/lib/hecks/bluebook/smoke_test.rb +166 -0
  150. data/lib/hecks/bluebook/synthesizer.rb +95 -0
  151. data/lib/hecks/bluebook/translation.rb +92 -0
  152. data/lib/hecks/bluebook/value_object.rb +58 -0
  153. data/lib/hecks/bluebook.rb +74 -0
  154. data/lib/hecks/codemod.rb +342 -0
  155. data/lib/hecks/construct.rb +71 -0
  156. data/lib/hecks/deploy/bluebook/deploy.bluebook +219 -0
  157. data/lib/hecks/deploy/bluebook/deploy.hecksagon +4 -0
  158. data/lib/hecks/deploy/oidc.json +18 -0
  159. data/lib/hecks/doc/reference.rb +389 -0
  160. data/lib/hecks/embryonaut_bluebook.rb +75 -0
  161. data/lib/hecks/facade/cli_door.rb +116 -0
  162. data/lib/hecks/facade/cli_runner.rb +190 -0
  163. data/lib/hecks/facade/command_request.rb +105 -0
  164. data/lib/hecks/facade/handle.rb +173 -0
  165. data/lib/hecks/facade/json_door.rb +154 -0
  166. data/lib/hecks/facade/surface/aggregate_door.rb +185 -0
  167. data/lib/hecks/facade/surface/chapter.rb +107 -0
  168. data/lib/hecks/facade/surface.rb +48 -0
  169. data/lib/hecks/facade.rb +44 -0
  170. data/lib/hecks/forms/app.rb +300 -0
  171. data/lib/hecks/forms/command_form_renderer.rb +113 -0
  172. data/lib/hecks/forms/examples/banking_console.bluebook +3 -0
  173. data/lib/hecks/forms/field_renderer.rb +170 -0
  174. data/lib/hecks/forms/field_shape.rb +232 -0
  175. data/lib/hecks/forms/html.rb +53 -0
  176. data/lib/hecks/forms/index_renderer.rb +35 -0
  177. data/lib/hecks/forms/page.rb +157 -0
  178. data/lib/hecks/forms/params.rb +132 -0
  179. data/lib/hecks/forms/query_form_renderer.rb +114 -0
  180. data/lib/hecks/forms/record_renderer.rb +115 -0
  181. data/lib/hecks/forms/record_table.rb +63 -0
  182. data/lib/hecks/forms/reference_options.rb +30 -0
  183. data/lib/hecks/forms/value_object_shape.rb +46 -0
  184. data/lib/hecks/forms.rb +54 -0
  185. data/lib/hecks/fqn.rb +94 -0
  186. data/lib/hecks/framework/bluebook/compliance.bluebook +1 -0
  187. data/lib/hecks/framework/bluebook/console_settings.bluebook +489 -0
  188. data/lib/hecks/framework/bluebook/framework.hecksagon +32 -0
  189. data/lib/hecks/framework/bluebook/governance.bluebook +130 -0
  190. data/lib/hecks/framework/bluebook/identity.bluebook +90 -0
  191. data/lib/hecks/framework/oidc.json +39 -0
  192. data/lib/hecks/framework.rb +90 -0
  193. data/lib/hecks/freezer.rb +67 -0
  194. data/lib/hecks/fuzzing/invalid_value_generator.rb +86 -0
  195. data/lib/hecks/fuzzing/isolated_boot.rb +92 -0
  196. data/lib/hecks/fuzzing/properties.rb +1146 -0
  197. data/lib/hecks/fuzzing/replay.rb +635 -0
  198. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +93 -0
  199. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +54 -0
  200. data/lib/hecks/fuzzing/sequence_generator/picker.rb +96 -0
  201. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +185 -0
  202. data/lib/hecks/fuzzing/sequence_generator.rb +130 -0
  203. data/lib/hecks/fuzzing/value_generator.rb +177 -0
  204. data/lib/hecks/fuzzing.rb +12 -0
  205. data/lib/hecks/grammar/evolve.rb +291 -0
  206. data/lib/hecks/grammar/expression.bluebook +417 -0
  207. data/lib/hecks/grammar/expression_operators.json +1152 -0
  208. data/lib/hecks/grammar/grammar.hecksagon +20 -0
  209. data/lib/hecks/grammar/oidc.json +69 -0
  210. data/lib/hecks/grammar/translation.bluebook +203 -0
  211. data/lib/hecks/grammar.rb +178 -0
  212. data/lib/hecks/ir.rb +126 -0
  213. data/lib/hecks/language/adapter.bluebook +116 -0
  214. data/lib/hecks/language/bluebook/aggregate.bluebook +581 -0
  215. data/lib/hecks/language/bluebook/attaches/paging.bluebook +76 -0
  216. data/lib/hecks/language/bluebook/bluebook.bluebook +256 -0
  217. data/lib/hecks/language/bluebook/bluebook.hecksagon +24 -0
  218. data/lib/hecks/language/bluebook/command.bluebook +437 -0
  219. data/lib/hecks/language/bluebook/entity.bluebook +316 -0
  220. data/lib/hecks/language/bluebook/policy.bluebook +172 -0
  221. data/lib/hecks/language/bluebook/process_manager.bluebook +264 -0
  222. data/lib/hecks/language/bluebook/projection.bluebook +267 -0
  223. data/lib/hecks/language/bluebook/query.bluebook +245 -0
  224. data/lib/hecks/language/bluebook/shape.bluebook +292 -0
  225. data/lib/hecks/language/bluebook/syntax.bluebook +447 -0
  226. data/lib/hecks/language/bluebook/vocabulary.bluebook +364 -0
  227. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +51 -0
  228. data/lib/hecks/language/hecksagon/domain_port.bluebook +76 -0
  229. data/lib/hecks/language/hecksagon/hecksagon.bluebook +131 -0
  230. data/lib/hecks/language/hecksagon/port_operation.bluebook +102 -0
  231. data/lib/hecks/language/oidc.json +313 -0
  232. data/lib/hecks/language/port.bluebook +92 -0
  233. data/lib/hecks/language/translation/translation.bluebook +110 -0
  234. data/lib/hecks/language/translation/translation_aggregate.bluebook +267 -0
  235. data/lib/hecks/language/world/wiring.bluebook +62 -0
  236. data/lib/hecks/language/world/world.bluebook +84 -0
  237. data/lib/hecks/literal.rb +125 -0
  238. data/lib/hecks/naming.rb +121 -0
  239. data/lib/hecks/ports/access_control.port +4 -0
  240. data/lib/hecks/ports/access_control.rb +62 -0
  241. data/lib/hecks/ports/agent/answers.rb +104 -0
  242. data/lib/hecks/ports/agent.port +4 -0
  243. data/lib/hecks/ports/agent.rb +167 -0
  244. data/lib/hecks/ports/authentication.port +4 -0
  245. data/lib/hecks/ports/authentication.rb +50 -0
  246. data/lib/hecks/ports/authorization.port +4 -0
  247. data/lib/hecks/ports/authorization.rb +59 -0
  248. data/lib/hecks/ports/clock.port +4 -0
  249. data/lib/hecks/ports/clock.rb +62 -0
  250. data/lib/hecks/ports/extraction.port +4 -0
  251. data/lib/hecks/ports/extraction.rb +37 -0
  252. data/lib/hecks/ports/identity_assignment.port +4 -0
  253. data/lib/hecks/ports/identity_assignment.rb +45 -0
  254. data/lib/hecks/ports/identity_generation.port +4 -0
  255. data/lib/hecks/ports/identity_generation.rb +49 -0
  256. data/lib/hecks/ports/identity_resolution.port +4 -0
  257. data/lib/hecks/ports/identity_resolution.rb +40 -0
  258. data/lib/hecks/ports/loading.port +4 -0
  259. data/lib/hecks/ports/loading.rb +13 -0
  260. data/lib/hecks/ports/persistence/append_only.rb +102 -0
  261. data/lib/hecks/ports/persistence/binding_policy.rb +56 -0
  262. data/lib/hecks/ports/persistence/execution.rb +18 -0
  263. data/lib/hecks/ports/persistence/lineage.rb +277 -0
  264. data/lib/hecks/ports/persistence/null_saga_store.rb +25 -0
  265. data/lib/hecks/ports/persistence/remote_runtime.rb +42 -0
  266. data/lib/hecks/ports/persistence/repository_factory.rb +30 -0
  267. data/lib/hecks/ports/persistence.port +4 -0
  268. data/lib/hecks/ports/persistence.rb +39 -0
  269. data/lib/hecks/ports/projection.port +4 -0
  270. data/lib/hecks/ports/projection.rb +76 -0
  271. data/lib/hecks/ports/query/in_memory.rb +60 -0
  272. data/lib/hecks/ports/query/ordering.rb +41 -0
  273. data/lib/hecks/ports/query.rb +36 -0
  274. data/lib/hecks/ports.rb +27 -0
  275. data/lib/hecks/projections/diagrams.rb +413 -0
  276. data/lib/hecks/projections/ir.rb +18 -0
  277. data/lib/hecks/projections/model/deviations.rb +98 -0
  278. data/lib/hecks/projections/model.rb +145 -0
  279. data/lib/hecks/projections/oidc.rb +110 -0
  280. data/lib/hecks/projections/parser_table.rb +159 -0
  281. data/lib/hecks/projections/reference.rb +38 -0
  282. data/lib/hecks/projections/shape.rb +31 -0
  283. data/lib/hecks/projections/statements.rb +110 -0
  284. data/lib/hecks/projections/vocabulary.rb +100 -0
  285. data/lib/hecks/projections.rb +32 -0
  286. data/lib/hecks/projector/cli_projector.rb +437 -0
  287. data/lib/hecks/projector/docs_projector.rb +321 -0
  288. data/lib/hecks/projector/exporter.rb +141 -0
  289. data/lib/hecks/projector/ir_projector.rb +18 -0
  290. data/lib/hecks/projector/narrate_projector.rb +243 -0
  291. data/lib/hecks/projector/target.rb +97 -0
  292. data/lib/hecks/projector.rb +186 -0
  293. data/lib/hecks/query_ir.rb +392 -0
  294. data/lib/hecks/query_specification/common/authorization_spec.rb +9 -0
  295. data/lib/hecks/query_specification/common/comparators.rb +25 -0
  296. data/lib/hecks/query_specification/common/comparison.rb +174 -0
  297. data/lib/hecks/query_specification/common/cursor_spec.rb +9 -0
  298. data/lib/hecks/query_specification/common/dsl.rb +58 -0
  299. data/lib/hecks/query_specification/common/inspection_spec.rb +9 -0
  300. data/lib/hecks/query_specification/common/limit_spec.rb +9 -0
  301. data/lib/hecks/query_specification/common/null_policy.rb +80 -0
  302. data/lib/hecks/query_specification/common/null_semantics.rb +11 -0
  303. data/lib/hecks/query_specification/common/offset_spec.rb +9 -0
  304. data/lib/hecks/query_specification/common/options.rb +32 -0
  305. data/lib/hecks/query_specification/common/order_by.rb +9 -0
  306. data/lib/hecks/query_specification/common/specification.rb +10 -0
  307. data/lib/hecks/query_specification/common/where_clause.rb +9 -0
  308. data/lib/hecks/query_specification/field_path.rb +89 -0
  309. data/lib/hecks/query_specification/hop_path.rb +130 -0
  310. data/lib/hecks/query_specification/read_model/specification.rb +18 -0
  311. data/lib/hecks/query_specification.rb +14 -0
  312. data/lib/hecks/rendering.rb +48 -0
  313. data/lib/hecks/router/namespace_installer.rb +157 -0
  314. data/lib/hecks/router.rb +70 -0
  315. data/lib/hecks/runtime/caller.rb +50 -0
  316. data/lib/hecks/runtime/capability_graph.rb +44 -0
  317. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +124 -0
  318. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +248 -0
  319. data/lib/hecks/runtime/command_interpreter.rb +413 -0
  320. data/lib/hecks/runtime/command_rules/admissibility.rb +307 -0
  321. data/lib/hecks/runtime/command_rules/arithmetic.rb +254 -0
  322. data/lib/hecks/runtime/command_rules/authorization.rb +64 -0
  323. data/lib/hecks/runtime/command_rules/emission.rb +34 -0
  324. data/lib/hecks/runtime/command_rules/references.rb +181 -0
  325. data/lib/hecks/runtime/command_rules.rb +28 -0
  326. data/lib/hecks/runtime/dependency_planning.rb +231 -0
  327. data/lib/hecks/runtime/dispatcher.rb +286 -0
  328. data/lib/hecks/runtime/entity_element.rb +253 -0
  329. data/lib/hecks/runtime/entity_interpreter.rb +228 -0
  330. data/lib/hecks/runtime/era_check.rb +136 -0
  331. data/lib/hecks/runtime/era_guard/shape_diff.rb +128 -0
  332. data/lib/hecks/runtime/era_guard.rb +193 -0
  333. data/lib/hecks/runtime/era_tamper.rb +61 -0
  334. data/lib/hecks/runtime/errors.rb +100 -0
  335. data/lib/hecks/runtime/event.rb +51 -0
  336. data/lib/hecks/runtime/identity.rb +128 -0
  337. data/lib/hecks/runtime/instance.rb +120 -0
  338. data/lib/hecks/runtime/interpreting.rb +69 -0
  339. data/lib/hecks/runtime/loader.rb +143 -0
  340. data/lib/hecks/runtime/policy_interpreter.rb +366 -0
  341. data/lib/hecks/runtime/port_operation_interpreter.rb +210 -0
  342. data/lib/hecks/runtime/query_interpreter.rb +254 -0
  343. data/lib/hecks/runtime/reaction_invocation.rb +245 -0
  344. data/lib/hecks/runtime/read_model_interpreter.rb +266 -0
  345. data/lib/hecks/runtime/rebuild_sweep.rb +74 -0
  346. data/lib/hecks/runtime/reference_hop.rb +99 -0
  347. data/lib/hecks/runtime/refusal_wording.rb +124 -0
  348. data/lib/hecks/runtime/registry/saga_persistence.rb +70 -0
  349. data/lib/hecks/runtime/registry/verification.rb +158 -0
  350. data/lib/hecks/runtime/registry.rb +218 -0
  351. data/lib/hecks/runtime/remote_dispatcher.rb +143 -0
  352. data/lib/hecks/runtime/routing.rb +96 -0
  353. data/lib/hecks/runtime/saga_interpreter/correlation.rb +97 -0
  354. data/lib/hecks/runtime/saga_interpreter.rb +301 -0
  355. data/lib/hecks/runtime/storage_shape.rb +120 -0
  356. data/lib/hecks/runtime/tenant_check.rb +84 -0
  357. data/lib/hecks/runtime/tenant_scope.rb +55 -0
  358. data/lib/hecks/runtime/value/admission.rb +112 -0
  359. data/lib/hecks/runtime/value/coercion.rb +500 -0
  360. data/lib/hecks/runtime/value/invariant_violation.rb +5 -0
  361. data/lib/hecks/runtime/value.rb +125 -0
  362. data/lib/hecks/runtime.rb +95 -0
  363. data/lib/hecks/translation/audit/approval_digest.rb +31 -0
  364. data/lib/hecks/translation/audit/layer_one.rb +37 -0
  365. data/lib/hecks/translation/audit/layer_two.rb +77 -0
  366. data/lib/hecks/translation/audit/unfed_report.rb +42 -0
  367. data/lib/hecks/translation/audit.rb +70 -0
  368. data/lib/hecks/translation/reattest.rb +72 -0
  369. data/lib/hecks/translation/rule_compiler.rb +120 -0
  370. data/lib/hecks/translation/scaffold/differ.rb +183 -0
  371. data/lib/hecks/translation/scaffold/renderer.rb +41 -0
  372. data/lib/hecks/translation/scaffold/writer.rb +28 -0
  373. data/lib/hecks/translation/scaffold.rb +30 -0
  374. data/lib/hecks/translation.rb +11 -0
  375. data/lib/hecks/version.rb +16 -0
  376. data/lib/hecks/vocabulary.rb +213 -0
  377. data/lib/hecks.rb +118 -6
  378. metadata +401 -222
  379. data/bin/hecks +0 -7
  380. data/bin/hecks-package +0 -65
  381. data/bin/hecks_console +0 -12
  382. data/bin/hecks_serverless +0 -6
  383. data/lib/cli/build.rb +0 -14
  384. data/lib/cli/command_runner.rb +0 -28
  385. data/lib/cli/console.rb +0 -10
  386. data/lib/cli/generate.rb +0 -37
  387. data/lib/cli/hecks-cli.rb +0 -27
  388. data/lib/cli/test.rb +0 -57
  389. data/lib/console/commands.rb +0 -8
  390. data/lib/console/hecks-console.rb +0 -1
  391. data/lib/packager/README.md +0 -0
  392. data/lib/packager/app_runner.rb +0 -21
  393. data/lib/packager/args.rb +0 -26
  394. data/lib/packager/compatibility/fixnum.rb +0 -6
  395. data/lib/packager/hecks.rb +0 -39
  396. data/lib/packager/query_runner.rb +0 -21
  397. data/lib/packager/resources/Dockerfile +0 -11
  398. data/lib/packager/resources/app_binary +0 -7
  399. data/lib/packager/resources/bundle_config +0 -3
  400. data/lib/packager/resources/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz +0 -0
  401. data/lib/packager/resources/traveling-ruby-20150715-2.2.2-osx.tar.gz +0 -0
  402. data/lib/serverless/Domain +0 -32
  403. data/lib/serverless/cli.rb +0 -75
  404. data/lib/serverless/resources/command_name.js +0 -5
  405. data/lib/serverless/resources/environment.js +0 -7
  406. data/lib/serverless/resources/handler.js.tt +0 -28
  407. data/lib/serverless/resources/run_binary.js +0 -22
  408. data/lib/serverless/resources/serverless.yml +0 -20
@@ -0,0 +1,327 @@
1
+ module Hecks
2
+ module Bluebook
3
+ module DSL
4
+ module AttributeCollector
5
+ ListOf = Struct.new(:type)
6
+ OneOf = Struct.new(:values)
7
+
8
+ UNSET = Object.new.freeze
9
+ private_constant :UNSET
10
+
11
+ def attributes = @attributes ||= []
12
+
13
+ # Value objects synthesised from inline closed sets, collected here and
14
+ # installed by whoever owns value objects (the aggregate).
15
+ def closed_sets = @closed_sets ||= []
16
+
17
+ # `admits:` names a closed set that is ALREADY DECLARED elsewhere —
18
+ #
19
+ # attribute :op, String, admits: "Vocabulary::QueryComparator"
20
+ #
21
+ # which is the difference between it and `one_of`: `one_of` SYNTHESISES
22
+ # a fresh value object named for the attribute, so it can only ever name
23
+ # something new. `admits` points at a set the language already holds, so
24
+ # the same set can be named from many places without being written twice.
25
+ #
26
+ # QUALIFIED, because a closed set is a value object INSIDE an aggregate
27
+ # and `reference_to` reaches heads only — so this is text, checked where
28
+ # it is read rather than by reference resolution.
29
+ #
30
+ # AND WRITTEN AS TEXT, not as the constant path `Vocabulary::QueryComparator`
31
+ # it reads like. The constant spelling was tried — `ConstShim` returning
32
+ # a Module so Ruby's `::` reaches a second `const_missing` — and it
33
+ # cannot hold: `Facade::Surface` installs every aggregate name as a
34
+ # TOP-LEVEL constant, so the moment any facade exists, `Vocabulary`
35
+ # resolves to that module and the shim is never asked. A spelling that
36
+ # works only until a facade is built is worse than a quoted one.
37
+ #
38
+ # THE TYPE POSITION TAKES A BARE CONSTANT, ALWAYS REQUIRED (ADR 0025,
39
+ # "Attributes") — omitting it (a mint default of String) and quoting
40
+ # it as text both refuse now. Neither had a real reason left: no
41
+ # corpus attribute ever omitted the type, and `ConstShim#const_missing`
42
+ # (S0b) already resolves a bare, not-yet-declared constant to the
43
+ # SAME forward reference the quoted form existed for — a bareword
44
+ # `Name` reaches a value object named "Name" declared later in the
45
+ # same block exactly as `"Name"` used to, `spell`'s own `to_s`
46
+ # renders either one identically. Neither form appears in any frozen
47
+ # era text (checked directly), so both are refused unconditionally —
48
+ # nothing for `MetaValidator.shadow_parsing?` to answer for.
49
+ # RENAMED FROM `attribute` — item #13's full metaprogrammed
50
+ # dispatch (slice 3, whole-project table-unification survey).
51
+ # The word `attribute` itself is no longer a real method any
52
+ # builder answers directly: every (context, word) Keyword row
53
+ # for it carries `calls: "attribute_impl"`, and `GenericDispatch`
54
+ # forwards the whole call here untouched — this method's own
55
+ # body is exactly what `attribute` always was, unchanged, just
56
+ # reached generically now rather than by Ruby's own direct
57
+ # method lookup. `attribute_collector_spec.rb` (`AttributeCollector
58
+ # has no method without a test` — dsl_coverage_spec.rb) and the
59
+ # bootstrap fallback (`GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`) both
60
+ # name this same string; they must never drift apart.
61
+ def attribute_impl(name, type = UNSET, default: nil, optional: false, pattern: nil,
62
+ admits: nil, one_of: nil)
63
+ # moved to the language: FieldName invariant, on Root.Attribute
64
+
65
+ if type.equal?(UNSET)
66
+ raise Malformed, "#{name} declares no type — attribute :#{name}, SomeType is required, " \
67
+ "there is no default"
68
+ end
69
+
70
+ # `list_of("X")` carries the same quoted text one level down — a
71
+ # bare constant is required there too, checked before it unwraps
72
+ # below, not after (once unwrapped, a plain String in the `type:`
73
+ # slot looks identical to one that legitimately belongs there).
74
+ quoted = type.is_a?(ListOf) ? type.type : type
75
+ if quoted.is_a?(::String)
76
+ raise Malformed, "#{name}'s type #{quoted.inspect} is quoted text — give the bare constant " \
77
+ "(#{quoted}) instead; a forward reference to a value object declared later " \
78
+ "in the same block already resolves without quoting"
79
+ end
80
+
81
+ refuse_unshared_pattern(name, pattern) if pattern
82
+
83
+ type = synthesise_closed_set(name, type) if type.is_a?(OneOf)
84
+ list = type.is_a?(ListOf)
85
+ attributes << Attribute.new(
86
+ name: name,
87
+ type: list ? type.type : type,
88
+ list: list,
89
+ default: default,
90
+ optional: optional,
91
+ pattern: pattern,
92
+ admits: admits
93
+ )
94
+
95
+ install_inline_closed_set(name, one_of) if one_of
96
+ end
97
+
98
+ # RENAMED FROM `list_of` — item #13's full metaprogrammed
99
+ # dispatch (slice 5). Called in an attribute's own TYPE
100
+ # position (`attribute :x, list_of(Y)`), never through a `def
101
+ # list_of` any ONE builder answers as its own word — reached
102
+ # via `WordGate#word_gate_dispatch`'s new "Type"-context
103
+ # fallback, the same one `one_of_impl` below uses. Bootstrap-
104
+ # reachable (every core chapter's own list-typed attributes use
105
+ # it), so `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK` carries a
106
+ # SINGLE `["Type", "list_of"]` entry rather than one per calling
107
+ # context — the bootstrap branch checks that key too now, same
108
+ # reasoning as the ordinary fallback.
109
+ def list_of_impl(type) = ListOf.new(type)
110
+
111
+ # `reference_to Account` MINTS `:account` — no `_id` — the default
112
+ # every `reference_to`-shaped word (`AggregateBuilder`,
113
+ # `EntityBuilder`, `CommandBuilder#cross_reference`,
114
+ # `QueryBuilder`, `PortOperationBuilder`, all `include
115
+ # AttributeCollector`) shares, since dropping the suffix is what
116
+ # makes `/` a real traversal operator possible at all (ADR 0025,
117
+ # "References" — a hop crosses at `/`, a field walk crosses at
118
+ # `.`; deriving the hop name from `account_id` is what made an
119
+ # explicit operator impossible before).
120
+ #
121
+ # LEGACY UNDER SHADOW-PARSING (S0a's own bridge): frozen era text
122
+ # was minted under the OLD default, and `EraGuard.shadow_parse`
123
+ # reconstructs a held aggregate's shape to DIFF against the
124
+ # current one — reading that text through the NEW default would
125
+ # silently reconstruct the WRONG historical name, not merely
126
+ # refuse a spelling the way S1's `identified_by` legacy forms do.
127
+ # This is a mint DEFAULT changing, not a syntax being removed, so
128
+ # there is nothing to refuse here — only a fork in what gets
129
+ # minted when `as:` is omitted.
130
+ private def default_reference_name(target)
131
+ suffix = MetaValidator.shadow_parsing? ? "_id" : ""
132
+ :"#{Naming.snake(target)}#{suffix}"
133
+ end
134
+
135
+ # A closed set declared INLINE on the attribute:
136
+ #
137
+ # attribute :status, one_of("open", "shut")
138
+ #
139
+ # Desugars to a value object named for the attribute, so it goes through
140
+ # exactly the machinery a hand-written one_of does — and so the
141
+ # attribute's type is still a DECLARED value object, which is now a
142
+ # structural rule rather than a predicate.
143
+ #
144
+ # An earlier reading of this spelling parsed it and threw the values
145
+ # away: the attribute became a plain String and the closed set meant
146
+ # nothing, in a construct that looked supported. The desugaring is
147
+ # pinned now — the same bluebook must always yield the same IR.
148
+ # RENAMED FROM `one_of` — item #13's full metaprogrammed dispatch
149
+ # (slice 5), same reasoning as list_of_impl above. SAME NAME as
150
+ # `ValueObjectBuilder#one_of_impl`'s own override on purpose —
151
+ # that method's own `super(*values)` call (the no-block, bare
152
+ # type-position case) resolves by METHOD NAME up the ancestor
153
+ # chain, and renaming only one side would silently break it.
154
+ def one_of_impl(*values) = OneOf.new(values)
155
+
156
+ private
157
+
158
+ def relationship_attribute(target, kind, name, optional: false, list: false)
159
+ attributes << Attribute.new(
160
+ name: name,
161
+ type: Reference.new(target),
162
+ list: list,
163
+ optional: optional,
164
+ relationship: kind
165
+ )
166
+ end
167
+
168
+ # `one_of:` NAMES A CLOSED SET ON THE FIELD ITSELF (ADR 0025,
169
+ # "Attributes") — joining `pattern:`/`admits:` where value
170
+ # constraints already live, for the one context where it means
171
+ # anything: a `value_object` block, where it replaces the old
172
+ # `one_of do member ... end` wrapper for a SINGLE-FIELD set (a
173
+ # multi-field set still writes bare `member` lines, unwrapped).
174
+ # `ValueObjectBuilder` overrides this; every other includer
175
+ # (Aggregate/Entity/Command/Query/PortOperation) inherits this
176
+ # refusal — those contexts already have the unchanged type-position
177
+ # form (`attribute :status, one_of("open", "shut")`) for an
178
+ # anonymous inline set, so `one_of:` naming a *field* there would be
179
+ # a second spelling of the same idea, not a new one.
180
+ def install_inline_closed_set(name, _values)
181
+ raise Malformed,
182
+ "#{name}'s one_of: only means something inside a value_object — name a closed set " \
183
+ "with the type-position one_of(...) instead"
184
+ end
185
+
186
+ # A pattern is refused AT DECLARATION, not when a value first meets it :
187
+ # a regex whose meaning depends on which engine reads it is a defect in
188
+ # the bluebook, and a bluebook that loads is one whose patterns carry
189
+ # one meaning. PatternSubset says which those are, and why each is refused.
190
+ def refuse_unshared_pattern(name, pattern)
191
+ rejection = PatternSubset.validate(pattern)
192
+ return unless rejection
193
+
194
+ raise Malformed,
195
+ "#{name}'s pattern #{pattern.inspect} uses a #{rejection.construct} — " \
196
+ "#{rejection.reason}"
197
+ end
198
+
199
+ def synthesise_closed_set(name, one_of)
200
+ type = Naming.pascal(name)
201
+ closed_sets << ValueObject.declare(
202
+ name: type,
203
+ attributes: [Attribute.new(name: :value, type: "String")],
204
+ members: one_of.values.map { |value| { value: value.to_s } },
205
+ closed_set: true
206
+ )
207
+ type
208
+ end
209
+
210
+ # Every selected identity head contributes all of its recursively
211
+ # scalar leaves in declaration order. Named, inline and compound-key
212
+ # declarations therefore share one flattening rule.
213
+ def resolve_identity_field!(field, value_objects, context_name)
214
+ attr = attributes.find { |a| a.name == field }
215
+
216
+ # `:id` OR AN `_id`-SUFFIXED NAME WITH NO MATCHING ATTRIBUTE is
217
+ # not a typo to refuse — it is the language's own WALK-PARENT/
218
+ # FALLBACK-IDENTITY convention. The `_id` suffix is the meta-
219
+ # domain's own (the `Command`/`Entity`/`Aggregate` etc. records
220
+ # identify by `owner_id`/`bluebook_id`/`aggregate_id`, supplied
221
+ # by the judge's replay rather than declared locally — see
222
+ # `behavior.bluebook`'s own "owner_id is not a declared
223
+ # attribute" comment); bare `:id` is `Instance#materialize_
224
+ # identity!`'s own fallback name (`@aggregate.identified_by ||
225
+ # :id`) made explicit rather than left implicit — declaring
226
+ # `identified_by :id` says out loud what omitting `identified_by`
227
+ # entirely already meant. `reference_to` mints the `_id` suffix
228
+ # for the same reason `attr.reference?` below resolves bare: an
229
+ # `_id`(-shaped) name is already a scalar by the language's own
230
+ # spelling convention, walk-supplied or locally declared alike.
231
+ return [field.to_s] if attr.nil? && (field.to_s == "id" || field.to_s.end_with?("_id"))
232
+
233
+ raise Malformed, "#{context_name}.identified_by :#{field} names no attribute #{context_name} declares" unless attr
234
+
235
+ identity_paths_for_attribute(attr, value_objects, context_name, field.to_s, [])
236
+ end
237
+
238
+ # A named or inline identity mints one structured field, then expands
239
+ # each scalar leaf beneath it into the existing path-shaped IR.
240
+ def resolve_identity_type!(type, as, insert_at, value_objects, context_name)
241
+ target = Naming.demodulise(type.respond_to?(:hecks_name) ? type.hecks_name : type)
242
+ matches = value_objects.select { |value_object| value_object.hecks_name.to_s == target }
243
+ if matches.size > 1
244
+ raise Malformed, "#{context_name}.identified_by names duplicate value object #{target}"
245
+ end
246
+
247
+ vo = type.respond_to?(:attributes) ? type : matches.first
248
+ raise Malformed, "#{context_name}.identified_by names #{target}, which is not a declared value object" unless vo
249
+ if vo.attributes.empty?
250
+ raise Malformed, "#{context_name}.identified_by names #{target}, which declares no attributes"
251
+ end
252
+
253
+ field = (as || Naming.snake(target)).to_sym
254
+ if attributes.any? { |attribute| attribute.name == field }
255
+ raise Malformed,
256
+ "#{context_name}.identified_by #{target} mints :#{field}, but that attribute is already declared"
257
+ end
258
+
259
+ # `Attribute.new` DIRECTLY, not the public `attribute(...)` DSL
260
+ # entry — `target` is `Naming.demodulise`'d TEXT, not a bareword
261
+ # the bluebook author typed (the type position's own quoted-text
262
+ # refusal is about DSL source, not internal minting), and `vo`
263
+ # ITSELF can't be passed either: it is the real, already-built
264
+ # `ValueObject` subclass, permanently anonymous from Ruby's own
265
+ # `to_s` (only `hecks_name` carries its name) — `Attribute#spell`
266
+ # would demodulise it to "#<Class:0x...>", not "PizzaName".
267
+ attributes << Attribute.new(name: field, type: target)
268
+ # MOVED to `insert_at` — the attribute count AT THE MOMENT
269
+ # `identified_by` was actually called, captured by the caller —
270
+ # not left where `attribute` just appended it. Resolution happens
271
+ # at BUILD time, after every other attribute in the block has
272
+ # already run, so appending would put the identity field LAST
273
+ # regardless of where `identified_by` was actually written.
274
+ # Most real bluebooks write it first (insert_at 0); one (a
275
+ # ScheduledPayment corpus member) writes it after a reference_to
276
+ # and an attribute — this matches either, and whatever a person
277
+ # hand-writing `attribute field, Type` at that exact point,
278
+ # the way this used to be required, would have produced.
279
+ attributes.insert(insert_at, attributes.pop)
280
+ vo.attributes.flat_map do |attribute|
281
+ identity_paths_for_attribute(attribute, value_objects, context_name,
282
+ "#{field}.#{attribute.name}", [target])
283
+ end
284
+ end
285
+
286
+ def identity_paths_for_attribute(attribute, value_objects, context_name, path, visited)
287
+ if attribute.list?
288
+ raise Malformed,
289
+ "#{context_name}'s identity member #{path} is a list — an identity member must be scalar"
290
+ end
291
+ if attribute.optional?
292
+ raise Malformed,
293
+ "#{context_name}'s identity member #{path} is optional — an identity must be wholly known"
294
+ end
295
+
296
+ return [path] if attribute.reference?
297
+
298
+ nested = value_objects.find { |value_object| value_object.hecks_name.to_s == attribute.type.to_s }
299
+ return [path] unless nested
300
+
301
+ if visited.include?(nested.hecks_name.to_s)
302
+ cycle = [*visited, nested.hecks_name.to_s].join(" -> ")
303
+ raise Malformed, "#{context_name}'s identity value objects form a cycle: #{cycle}"
304
+ end
305
+
306
+ # A BARE FIELD DERIVES ONE SCALAR. `identified_by :ref` (or one leg
307
+ # of a compound `identified_by :a, :b`) names a single field, and
308
+ # deriving ITS path only makes sense while every value object along
309
+ # the way wraps exactly one field itself — the same "single-field
310
+ # value object" ADR 0025 names this shape after. A multi-field
311
+ # value object here used to expand silently into every one of its
312
+ # own fields, minting an unannounced compound key nothing declared.
313
+ if nested.attributes.size != 1
314
+ candidates = nested.attributes.map(&:name).join(", ")
315
+ raise Malformed,
316
+ "#{context_name}.identified_by :#{path} names #{nested.hecks_name}, which has " \
317
+ "#{nested.attributes.size} field#{'s' unless nested.attributes.size == 1} (#{candidates})"
318
+ end
319
+
320
+ member = nested.attributes.first
321
+ identity_paths_for_attribute(member, value_objects, context_name, "#{path}.#{member.name}",
322
+ [*visited, nested.hecks_name.to_s])
323
+ end
324
+ end
325
+ end
326
+ end
327
+ end
@@ -0,0 +1,71 @@
1
+ module Hecks
2
+ module Bluebook
3
+ module DSL
4
+ class BindingProxy
5
+ def self.namespace(domain, collector)
6
+ Module.new do
7
+ define_singleton_method(:const_missing) do |aggregate|
8
+ BindingProxy.new("#{domain}::#{aggregate}", collector)
9
+ end
10
+ end
11
+ end
12
+
13
+ def initialize(fqn, collector)
14
+ @fqn = fqn
15
+ @collector = collector
16
+ end
17
+
18
+ # THE AGGREGATE-SCOPED PORT — `Payments::Payment.port("Gateway") do
19
+ # ... end`, the same receiver a plain bind like `.persisted_by(...)`
20
+ # already reaches, because a port belongs to exactly one aggregate
21
+ # the same way a bind does. A REAL method, not method_missing : its
22
+ # shape (a name and a block building operations) has nothing to do
23
+ # with `Bind`, so it does not belong in that generic verb path.
24
+ def port(name, &block)
25
+ domain, aggregate_name = @fqn.split("::")
26
+ aggregate_ir = Hecks.current_registry.bluebook(domain)&.aggregate(aggregate_name) or
27
+ raise Malformed, "#{@fqn} declares no such aggregate — a port needs one to belong to"
28
+
29
+ # See HecksagonBuilder#port's own comment on why this resolver
30
+ # swap is needed : ConstShim's active resolver is one global for
31
+ # the whole dynamic extent, and it is currently this file's own
32
+ # BindingProxy-minting one, which would turn a bare `Pizza` inside
33
+ # `reference_to Pizza` into another BindingProxy instead of a name.
34
+ built = ConstShim.with(->(const) { const }) { DomainPortBuilder.build(name, owner: aggregate_name, &block) }
35
+
36
+ # A `verb`-shaped port is a plain `Port` — the exact struct
37
+ # `Hecks.port`'s own top-level method registers, so it goes
38
+ # through the same `add_port` the registry already answers for
39
+ # that call. It belongs to no aggregate IR the way an
40
+ # operations-shaped `DomainPort` does; the aggregate above
41
+ # was only needed to resolve `owner` for the operations branch.
42
+ if built.is_a?(Port)
43
+ Hecks.current_registry.add_port(built)
44
+ return self
45
+ end
46
+
47
+ built.operations.each do |operation|
48
+ operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = aggregate_ir }
49
+ end
50
+ aggregate_ir.add_port(built)
51
+ self
52
+ end
53
+
54
+ def method_missing(verb, *args, **kwargs, &block)
55
+ @collector << Bind.new(
56
+ aggregate: @fqn,
57
+ verb: verb.to_s,
58
+ adapter: args.first.to_s,
59
+ role: kwargs[:role]&.to_s
60
+ )
61
+ block&.call
62
+ self
63
+ end
64
+
65
+ def respond_to_missing?(_name, _include_private = false) = true
66
+
67
+ def to_s = @fqn
68
+ end
69
+ end
70
+ end
71
+ end