hecks 0.2.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (419) 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 +427 -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 +101 -0
  12. data/lib/hecks/adapters/driven/heki/journal.rb +56 -0
  13. data/lib/hecks/adapters/driven/heki/saga_store.rb +99 -0
  14. data/lib/hecks/adapters/driven/heki/snapshot.rb +65 -0
  15. data/lib/hecks/adapters/driven/heki.adapter +4 -0
  16. data/lib/hecks/adapters/driven/heki.rb +179 -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 +145 -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 +88 -0
  28. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +207 -0
  29. data/lib/hecks/adapters/driven/postgres.adapter +5 -0
  30. data/lib/hecks/adapters/driven/postgres.rb +438 -0
  31. data/lib/hecks/adapters/driven/postgres_era.adapter +17 -0
  32. data/lib/hecks/adapters/driven/prism.adapter +3 -0
  33. data/lib/hecks/adapters/driven/prism.rb +80 -0
  34. data/lib/hecks/adapters/driven/secure_random_identity.adapter +3 -0
  35. data/lib/hecks/adapters/driven/secure_random_identity.rb +14 -0
  36. data/lib/hecks/adapters/driven/sql_query_builder.rb +221 -0
  37. data/lib/hecks/adapters/driven/sqlite/codec.rb +80 -0
  38. data/lib/hecks/adapters/driven/sqlite/projection.rb +172 -0
  39. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +192 -0
  40. data/lib/hecks/adapters/driven/sqlite.adapter +9 -0
  41. data/lib/hecks/adapters/driven/sqlite.rb +306 -0
  42. data/lib/hecks/adapters/driven/system_clock.adapter +3 -0
  43. data/lib/hecks/adapters/driven/system_clock.rb +14 -0
  44. data/lib/hecks/adapters/driven.rb +54 -0
  45. data/lib/hecks/adapters.rb +6 -0
  46. data/lib/hecks/behaviors/dsl.rb +125 -0
  47. data/lib/hecks/behaviors/expectations.rb +340 -0
  48. data/lib/hecks/behaviors/ir.rb +31 -0
  49. data/lib/hecks/behaviors/rspec.rb +42 -0
  50. data/lib/hecks/behaviors/runner.rb +96 -0
  51. data/lib/hecks/behaviors.rb +25 -0
  52. data/lib/hecks/bluebook/aggregate.rb +108 -0
  53. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +134 -0
  54. data/lib/hecks/bluebook/assembly/build.rb +48 -0
  55. data/lib/hecks/bluebook/assembly/contract.rb +112 -0
  56. data/lib/hecks/bluebook/assembly/contracts.rb +438 -0
  57. data/lib/hecks/bluebook/assembly/marks.rb +228 -0
  58. data/lib/hecks/bluebook/assembly/specializer.rb +70 -0
  59. data/lib/hecks/bluebook/assembly.rb +91 -0
  60. data/lib/hecks/bluebook/attribute.rb +96 -0
  61. data/lib/hecks/bluebook/behaviour/aggregate.rb +83 -0
  62. data/lib/hecks/bluebook/behaviour/attribute.rb +27 -0
  63. data/lib/hecks/bluebook/behaviour/chapter.rb +72 -0
  64. data/lib/hecks/bluebook/behaviour/command.rb +116 -0
  65. data/lib/hecks/bluebook/behaviour/domain_port.rb +25 -0
  66. data/lib/hecks/bluebook/behaviour/entity.rb +59 -0
  67. data/lib/hecks/bluebook/behaviour/hexagon.rb +50 -0
  68. data/lib/hecks/bluebook/behaviour/lifecycle.rb +68 -0
  69. data/lib/hecks/bluebook/behaviour/policy.rb +52 -0
  70. data/lib/hecks/bluebook/behaviour/process_manager.rb +51 -0
  71. data/lib/hecks/bluebook/behaviour/query.rb +10 -0
  72. data/lib/hecks/bluebook/behaviour/read_model.rb +29 -0
  73. data/lib/hecks/bluebook/behaviour/traits.rb +81 -0
  74. data/lib/hecks/bluebook/behaviour/value_object.rb +33 -0
  75. data/lib/hecks/bluebook/chapter.rb +78 -0
  76. data/lib/hecks/bluebook/command.rb +124 -0
  77. data/lib/hecks/bluebook/domain_port.rb +102 -0
  78. data/lib/hecks/bluebook/dsl/adapter_builder.rb +34 -0
  79. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +1018 -0
  80. data/lib/hecks/bluebook/dsl/attribute_collector.rb +348 -0
  81. data/lib/hecks/bluebook/dsl/binding_proxy.rb +71 -0
  82. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +1087 -0
  83. data/lib/hecks/bluebook/dsl/command_builder.rb +714 -0
  84. data/lib/hecks/bluebook/dsl/const_shim.rb +81 -0
  85. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +79 -0
  86. data/lib/hecks/bluebook/dsl/entity_builder.rb +430 -0
  87. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +366 -0
  88. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +163 -0
  89. data/lib/hecks/bluebook/dsl/identity_declaration.rb +191 -0
  90. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +44 -0
  91. data/lib/hecks/bluebook/dsl/malformed.rb +7 -0
  92. data/lib/hecks/bluebook/dsl/policy_builder.rb +135 -0
  93. data/lib/hecks/bluebook/dsl/port_builder.rb +39 -0
  94. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +142 -0
  95. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +306 -0
  96. data/lib/hecks/bluebook/dsl/query_builder.rb +113 -0
  97. data/lib/hecks/bluebook/dsl/read_model_builder.rb +233 -0
  98. data/lib/hecks/bluebook/dsl/rule_reference.rb +173 -0
  99. data/lib/hecks/bluebook/dsl/translation_builder.rb +243 -0
  100. data/lib/hecks/bluebook/dsl/value_object_builder.rb +178 -0
  101. data/lib/hecks/bluebook/dsl/word_gate.rb +228 -0
  102. data/lib/hecks/bluebook/dsl/world_builder.rb +117 -0
  103. data/lib/hecks/bluebook/dsl.rb +45 -0
  104. data/lib/hecks/bluebook/entity.rb +103 -0
  105. data/lib/hecks/bluebook/expression/canonical_form.rb +123 -0
  106. data/lib/hecks/bluebook/expression/evaluator.rb +304 -0
  107. data/lib/hecks/bluebook/expression/projection.json +218 -0
  108. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +233 -0
  109. data/lib/hecks/bluebook/expression/resolver.rb +781 -0
  110. data/lib/hecks/bluebook/expression.rb +13 -0
  111. data/lib/hecks/bluebook/hexagon.rb +60 -0
  112. data/lib/hecks/bluebook/lifecycle.rb +42 -0
  113. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +54 -0
  114. data/lib/hecks/bluebook/meta_validator/judge.rb +621 -0
  115. data/lib/hecks/bluebook/meta_validator/plan.rb +332 -0
  116. data/lib/hecks/bluebook/meta_validator/port_judge.rb +51 -0
  117. data/lib/hecks/bluebook/meta_validator/readings.rb +360 -0
  118. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +351 -0
  119. data/lib/hecks/bluebook/meta_validator/shapes.rb +266 -0
  120. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +255 -0
  121. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +138 -0
  122. data/lib/hecks/bluebook/meta_validator/world_judge.rb +78 -0
  123. data/lib/hecks/bluebook/meta_validator.rb +542 -0
  124. data/lib/hecks/bluebook/model_check.rb +445 -0
  125. data/lib/hecks/bluebook/pattern_subset.rb +184 -0
  126. data/lib/hecks/bluebook/policy.rb +41 -0
  127. data/lib/hecks/bluebook/process_manager.rb +128 -0
  128. data/lib/hecks/bluebook/project_discovery.rb +30 -0
  129. data/lib/hecks/bluebook/project_loader.rb +40 -0
  130. data/lib/hecks/bluebook/project_register.rb +82 -0
  131. data/lib/hecks/bluebook/query.rb +61 -0
  132. data/lib/hecks/bluebook/read_model.rb +109 -0
  133. data/lib/hecks/bluebook/reference.rb +74 -0
  134. data/lib/hecks/bluebook/smoke_test.rb +166 -0
  135. data/lib/hecks/bluebook/synthesizer.rb +95 -0
  136. data/lib/hecks/bluebook/translation.rb +92 -0
  137. data/lib/hecks/bluebook/value_object.rb +66 -0
  138. data/lib/hecks/bluebook.rb +74 -0
  139. data/lib/hecks/codemod.rb +342 -0
  140. data/lib/hecks/construct.rb +71 -0
  141. data/lib/hecks/deploy/bluebook/deploy.bluebook +219 -0
  142. data/lib/hecks/deploy/bluebook/deploy.hecksagon +4 -0
  143. data/lib/hecks/deploy/oidc.json +18 -0
  144. data/lib/hecks/doc/reference.rb +410 -0
  145. data/lib/hecks/embryonaut_bluebook.rb +75 -0
  146. data/lib/hecks/facade/cli_door.rb +119 -0
  147. data/lib/hecks/facade/cli_runner.rb +190 -0
  148. data/lib/hecks/facade/command_request.rb +105 -0
  149. data/lib/hecks/facade/handle.rb +173 -0
  150. data/lib/hecks/facade/json_door.rb +166 -0
  151. data/lib/hecks/facade/surface/aggregate_door.rb +185 -0
  152. data/lib/hecks/facade/surface/chapter.rb +107 -0
  153. data/lib/hecks/facade/surface.rb +48 -0
  154. data/lib/hecks/facade.rb +44 -0
  155. data/lib/hecks/forms/app.rb +341 -0
  156. data/lib/hecks/forms/command_form_renderer.rb +113 -0
  157. data/lib/hecks/forms/examples/banking_console.bluebook +3 -0
  158. data/lib/hecks/forms/field_renderer.rb +177 -0
  159. data/lib/hecks/forms/field_shape.rb +232 -0
  160. data/lib/hecks/forms/html.rb +84 -0
  161. data/lib/hecks/forms/index_renderer.rb +35 -0
  162. data/lib/hecks/forms/page.rb +157 -0
  163. data/lib/hecks/forms/params.rb +161 -0
  164. data/lib/hecks/forms/port_argument.rb +46 -0
  165. data/lib/hecks/forms/query_form_renderer.rb +114 -0
  166. data/lib/hecks/forms/record_renderer.rb +119 -0
  167. data/lib/hecks/forms/record_table.rb +68 -0
  168. data/lib/hecks/forms/reference_options.rb +30 -0
  169. data/lib/hecks/forms/value_object_shape.rb +46 -0
  170. data/lib/hecks/forms.rb +54 -0
  171. data/lib/hecks/fqn.rb +94 -0
  172. data/lib/hecks/framework/bluebook/compliance.bluebook +1 -0
  173. data/lib/hecks/framework/bluebook/console_settings.bluebook +489 -0
  174. data/lib/hecks/framework/bluebook/framework.hecksagon +32 -0
  175. data/lib/hecks/framework/bluebook/governance.bluebook +145 -0
  176. data/lib/hecks/framework/bluebook/identity.bluebook +90 -0
  177. data/lib/hecks/framework/oidc.json +39 -0
  178. data/lib/hecks/framework.rb +90 -0
  179. data/lib/hecks/freezer.rb +67 -0
  180. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +527 -0
  181. data/lib/hecks/fuzzing/invalid_value_generator.rb +86 -0
  182. data/lib/hecks/fuzzing/isolated_boot.rb +286 -0
  183. data/lib/hecks/fuzzing/properties.rb +1192 -0
  184. data/lib/hecks/fuzzing/replay.rb +668 -0
  185. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +93 -0
  186. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +80 -0
  187. data/lib/hecks/fuzzing/sequence_generator/picker.rb +96 -0
  188. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +250 -0
  189. data/lib/hecks/fuzzing/sequence_generator.rb +131 -0
  190. data/lib/hecks/fuzzing/value_generator.rb +200 -0
  191. data/lib/hecks/fuzzing.rb +12 -0
  192. data/lib/hecks/grammar/evolve.rb +324 -0
  193. data/lib/hecks/grammar/expression.bluebook +420 -0
  194. data/lib/hecks/grammar/expression_operators.json +1648 -0
  195. data/lib/hecks/grammar/grammar.hecksagon +20 -0
  196. data/lib/hecks/grammar/oidc.json +69 -0
  197. data/lib/hecks/grammar/translation.bluebook +203 -0
  198. data/lib/hecks/grammar.rb +178 -0
  199. data/lib/hecks/ir.rb +126 -0
  200. data/lib/hecks/language/adapter.bluebook +116 -0
  201. data/lib/hecks/language/bluebook/aggregate.bluebook +581 -0
  202. data/lib/hecks/language/bluebook/attaches/paging.bluebook +76 -0
  203. data/lib/hecks/language/bluebook/bluebook.bluebook +256 -0
  204. data/lib/hecks/language/bluebook/bluebook.hecksagon +24 -0
  205. data/lib/hecks/language/bluebook/command.bluebook +471 -0
  206. data/lib/hecks/language/bluebook/entity.bluebook +392 -0
  207. data/lib/hecks/language/bluebook/policy.bluebook +189 -0
  208. data/lib/hecks/language/bluebook/process_manager.bluebook +381 -0
  209. data/lib/hecks/language/bluebook/projection.bluebook +267 -0
  210. data/lib/hecks/language/bluebook/query.bluebook +245 -0
  211. data/lib/hecks/language/bluebook/shape.bluebook +292 -0
  212. data/lib/hecks/language/bluebook/syntax.bluebook +448 -0
  213. data/lib/hecks/language/bluebook/vocabulary.bluebook +379 -0
  214. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +51 -0
  215. data/lib/hecks/language/hecksagon/domain_port.bluebook +76 -0
  216. data/lib/hecks/language/hecksagon/hecksagon.bluebook +131 -0
  217. data/lib/hecks/language/hecksagon/port_operation.bluebook +102 -0
  218. data/lib/hecks/language/oidc.json +333 -0
  219. data/lib/hecks/language/port.bluebook +120 -0
  220. data/lib/hecks/language/translation/translation.bluebook +110 -0
  221. data/lib/hecks/language/translation/translation_aggregate.bluebook +267 -0
  222. data/lib/hecks/language/world/wiring.bluebook +62 -0
  223. data/lib/hecks/language/world/world.bluebook +84 -0
  224. data/lib/hecks/literal.rb +125 -0
  225. data/lib/hecks/naming.rb +174 -0
  226. data/lib/hecks/ports/access_control.port +9 -0
  227. data/lib/hecks/ports/access_control.rb +62 -0
  228. data/lib/hecks/ports/agent/answers.rb +104 -0
  229. data/lib/hecks/ports/agent.port +8 -0
  230. data/lib/hecks/ports/agent.rb +167 -0
  231. data/lib/hecks/ports/authentication.port +6 -0
  232. data/lib/hecks/ports/authentication.rb +50 -0
  233. data/lib/hecks/ports/authorization.port +7 -0
  234. data/lib/hecks/ports/authorization.rb +62 -0
  235. data/lib/hecks/ports/clock.port +5 -0
  236. data/lib/hecks/ports/clock.rb +62 -0
  237. data/lib/hecks/ports/extraction.port +5 -0
  238. data/lib/hecks/ports/extraction.rb +37 -0
  239. data/lib/hecks/ports/identity_assignment.port +5 -0
  240. data/lib/hecks/ports/identity_assignment.rb +45 -0
  241. data/lib/hecks/ports/identity_generation.port +5 -0
  242. data/lib/hecks/ports/identity_generation.rb +49 -0
  243. data/lib/hecks/ports/identity_resolution.port +5 -0
  244. data/lib/hecks/ports/identity_resolution.rb +40 -0
  245. data/lib/hecks/ports/loading.port +4 -0
  246. data/lib/hecks/ports/loading.rb +13 -0
  247. data/lib/hecks/ports/persistence/append_only.rb +138 -0
  248. data/lib/hecks/ports/persistence/binding_policy.rb +56 -0
  249. data/lib/hecks/ports/persistence/execution.rb +23 -0
  250. data/lib/hecks/ports/persistence/null_saga_store.rb +25 -0
  251. data/lib/hecks/ports/persistence/plugin.rb +54 -0
  252. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +169 -0
  253. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +128 -0
  254. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +161 -0
  255. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +61 -0
  256. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +304 -0
  257. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +171 -0
  258. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +190 -0
  259. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +478 -0
  260. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +166 -0
  261. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +314 -0
  262. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +168 -0
  263. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +170 -0
  264. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +134 -0
  265. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +137 -0
  266. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +89 -0
  267. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +85 -0
  268. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +43 -0
  269. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +132 -0
  270. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +74 -0
  271. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +758 -0
  272. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +120 -0
  273. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +31 -0
  274. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +46 -0
  275. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +102 -0
  276. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +46 -0
  277. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +70 -0
  278. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +72 -0
  279. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +120 -0
  280. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +183 -0
  281. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +41 -0
  282. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +28 -0
  283. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +30 -0
  284. data/lib/hecks/ports/persistence/plugins/era/translation.rb +11 -0
  285. data/lib/hecks/ports/persistence/plugins/era.rb +48 -0
  286. data/lib/hecks/ports/persistence/remote_runtime.rb +42 -0
  287. data/lib/hecks/ports/persistence/repository_factory.rb +30 -0
  288. data/lib/hecks/ports/persistence.port +4 -0
  289. data/lib/hecks/ports/persistence.rb +39 -0
  290. data/lib/hecks/ports/projection.port +4 -0
  291. data/lib/hecks/ports/projection.rb +96 -0
  292. data/lib/hecks/ports/query/in_memory.rb +60 -0
  293. data/lib/hecks/ports/query/ordering.rb +41 -0
  294. data/lib/hecks/ports/query.rb +36 -0
  295. data/lib/hecks/ports.rb +27 -0
  296. data/lib/hecks/projections/diagrams.rb +642 -0
  297. data/lib/hecks/projections/ir.rb +18 -0
  298. data/lib/hecks/projections/model/deviations.rb +98 -0
  299. data/lib/hecks/projections/model.rb +145 -0
  300. data/lib/hecks/projections/oidc.rb +110 -0
  301. data/lib/hecks/projections/parser_table.rb +159 -0
  302. data/lib/hecks/projections/reference.rb +38 -0
  303. data/lib/hecks/projections/shape.rb +44 -0
  304. data/lib/hecks/projections/statements.rb +110 -0
  305. data/lib/hecks/projections/vocabulary.rb +100 -0
  306. data/lib/hecks/projections.rb +32 -0
  307. data/lib/hecks/projector/cli_projector.rb +446 -0
  308. data/lib/hecks/projector/docs_projector.rb +321 -0
  309. data/lib/hecks/projector/exporter.rb +158 -0
  310. data/lib/hecks/projector/ir_projector.rb +18 -0
  311. data/lib/hecks/projector/narrate_projector.rb +243 -0
  312. data/lib/hecks/projector/target.rb +97 -0
  313. data/lib/hecks/projector.rb +186 -0
  314. data/lib/hecks/query_ir.rb +411 -0
  315. data/lib/hecks/query_specification/common/authorization_spec.rb +9 -0
  316. data/lib/hecks/query_specification/common/comparators.rb +25 -0
  317. data/lib/hecks/query_specification/common/comparison.rb +174 -0
  318. data/lib/hecks/query_specification/common/cursor_spec.rb +9 -0
  319. data/lib/hecks/query_specification/common/dsl.rb +58 -0
  320. data/lib/hecks/query_specification/common/inspection_spec.rb +9 -0
  321. data/lib/hecks/query_specification/common/limit_spec.rb +9 -0
  322. data/lib/hecks/query_specification/common/null_policy.rb +92 -0
  323. data/lib/hecks/query_specification/common/null_semantics.rb +11 -0
  324. data/lib/hecks/query_specification/common/offset_spec.rb +9 -0
  325. data/lib/hecks/query_specification/common/options.rb +32 -0
  326. data/lib/hecks/query_specification/common/order_by.rb +9 -0
  327. data/lib/hecks/query_specification/common/specification.rb +10 -0
  328. data/lib/hecks/query_specification/common/where_clause.rb +9 -0
  329. data/lib/hecks/query_specification/field_path.rb +107 -0
  330. data/lib/hecks/query_specification/hop_path.rb +132 -0
  331. data/lib/hecks/query_specification/read_model/specification.rb +18 -0
  332. data/lib/hecks/query_specification.rb +14 -0
  333. data/lib/hecks/rendering.rb +48 -0
  334. data/lib/hecks/router/namespace_installer.rb +157 -0
  335. data/lib/hecks/router.rb +70 -0
  336. data/lib/hecks/runtime/aggregate_lock.rb +45 -0
  337. data/lib/hecks/runtime/boot_gates.rb +41 -0
  338. data/lib/hecks/runtime/caller.rb +66 -0
  339. data/lib/hecks/runtime/capability_graph.rb +44 -0
  340. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +135 -0
  341. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +260 -0
  342. data/lib/hecks/runtime/command_interpreter.rb +497 -0
  343. data/lib/hecks/runtime/command_rules/admissibility.rb +357 -0
  344. data/lib/hecks/runtime/command_rules/arithmetic.rb +260 -0
  345. data/lib/hecks/runtime/command_rules/authorization.rb +65 -0
  346. data/lib/hecks/runtime/command_rules/emission.rb +34 -0
  347. data/lib/hecks/runtime/command_rules/references.rb +189 -0
  348. data/lib/hecks/runtime/command_rules.rb +28 -0
  349. data/lib/hecks/runtime/dependency_planning.rb +245 -0
  350. data/lib/hecks/runtime/dispatcher.rb +301 -0
  351. data/lib/hecks/runtime/entity_element.rb +253 -0
  352. data/lib/hecks/runtime/entity_interpreter.rb +299 -0
  353. data/lib/hecks/runtime/errors.rb +122 -0
  354. data/lib/hecks/runtime/event.rb +51 -0
  355. data/lib/hecks/runtime/identity.rb +156 -0
  356. data/lib/hecks/runtime/instance.rb +175 -0
  357. data/lib/hecks/runtime/interpreting.rb +90 -0
  358. data/lib/hecks/runtime/loader.rb +184 -0
  359. data/lib/hecks/runtime/policy_interpreter.rb +366 -0
  360. data/lib/hecks/runtime/port_operation_interpreter.rb +210 -0
  361. data/lib/hecks/runtime/query_interpreter.rb +286 -0
  362. data/lib/hecks/runtime/reaction_invocation.rb +253 -0
  363. data/lib/hecks/runtime/read_model_interpreter.rb +341 -0
  364. data/lib/hecks/runtime/rebuild_sweep.rb +74 -0
  365. data/lib/hecks/runtime/reference_hop.rb +99 -0
  366. data/lib/hecks/runtime/refusal_wording.rb +126 -0
  367. data/lib/hecks/runtime/registry/saga_persistence.rb +142 -0
  368. data/lib/hecks/runtime/registry/verification.rb +246 -0
  369. data/lib/hecks/runtime/registry.rb +279 -0
  370. data/lib/hecks/runtime/remote_dispatcher.rb +143 -0
  371. data/lib/hecks/runtime/routing.rb +96 -0
  372. data/lib/hecks/runtime/saga_interpreter/correlation.rb +97 -0
  373. data/lib/hecks/runtime/saga_interpreter.rb +503 -0
  374. data/lib/hecks/runtime/saga_pending_dispatch.rb +45 -0
  375. data/lib/hecks/runtime/tenant_check.rb +84 -0
  376. data/lib/hecks/runtime/tenant_scope.rb +55 -0
  377. data/lib/hecks/runtime/value/admission.rb +130 -0
  378. data/lib/hecks/runtime/value/coercion.rb +565 -0
  379. data/lib/hecks/runtime/value/invariant_violation.rb +5 -0
  380. data/lib/hecks/runtime/value.rb +125 -0
  381. data/lib/hecks/runtime.rb +107 -0
  382. data/lib/hecks/storehouse.rb +632 -0
  383. data/lib/hecks/version.rb +16 -0
  384. data/lib/hecks/vocabulary.rb +218 -0
  385. data/lib/hecks.rb +123 -6
  386. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +90 -0
  387. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +128 -0
  388. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +160 -0
  389. metadata +412 -222
  390. data/bin/hecks +0 -7
  391. data/bin/hecks-package +0 -65
  392. data/bin/hecks_console +0 -12
  393. data/bin/hecks_serverless +0 -6
  394. data/lib/cli/build.rb +0 -14
  395. data/lib/cli/command_runner.rb +0 -28
  396. data/lib/cli/console.rb +0 -10
  397. data/lib/cli/generate.rb +0 -37
  398. data/lib/cli/hecks-cli.rb +0 -27
  399. data/lib/cli/test.rb +0 -57
  400. data/lib/console/commands.rb +0 -8
  401. data/lib/console/hecks-console.rb +0 -1
  402. data/lib/packager/README.md +0 -0
  403. data/lib/packager/app_runner.rb +0 -21
  404. data/lib/packager/args.rb +0 -26
  405. data/lib/packager/compatibility/fixnum.rb +0 -6
  406. data/lib/packager/hecks.rb +0 -39
  407. data/lib/packager/query_runner.rb +0 -21
  408. data/lib/packager/resources/Dockerfile +0 -11
  409. data/lib/packager/resources/app_binary +0 -7
  410. data/lib/packager/resources/bundle_config +0 -3
  411. data/lib/packager/resources/traveling-ruby-20150715-2.2.2-linux-x86_64.tar.gz +0 -0
  412. data/lib/packager/resources/traveling-ruby-20150715-2.2.2-osx.tar.gz +0 -0
  413. data/lib/serverless/Domain +0 -32
  414. data/lib/serverless/cli.rb +0 -75
  415. data/lib/serverless/resources/command_name.js +0 -5
  416. data/lib/serverless/resources/environment.js +0 -7
  417. data/lib/serverless/resources/handler.js.tt +0 -28
  418. data/lib/serverless/resources/run_binary.js +0 -22
  419. data/lib/serverless/resources/serverless.yml +0 -20
@@ -0,0 +1,185 @@
1
+ require_relative "../../bluebook/dsl/hecksagon_builder"
2
+ require_relative "../../bluebook/dsl/domain_port_builder"
3
+ require_relative "../../bluebook/dsl/const_shim"
4
+ require_relative "../../bluebook/hexagon"
5
+ require_relative "../handle"
6
+ require_relative "../../naming"
7
+
8
+ module Hecks
9
+ module Facade
10
+ module Surface
11
+ # One aggregate's door: creating verbs as module methods returning
12
+ # the record in hand, CRUD delegation to the repository, the
13
+ # `persisted_by`-style binding collector a `.hecksagon` lands on, and
14
+ # the aggregate-scoped `port` a `.hecksagon` lands on beside it.
15
+ module AggregateDoor
16
+ def aggregate_module(dispatcher, domain, ir)
17
+ fqn = "#{domain}::#{ir.hecks_name}"
18
+ door = Module.new
19
+
20
+ ir.attributes.each do |attribute|
21
+ next unless RESERVED.include?(attribute.name.to_sym)
22
+
23
+ warn "[hecks] #{ir.hecks_name}##{attribute.name} shadows a built-in — no reader defined"
24
+ end
25
+
26
+ # A creating verb is a MODULE method returning the new record in hand ;
27
+ # a verb that reaches an existing record lives on the Handle. `!` —
28
+ # a command DOES something (mutates, may refuse), Ruby's own
29
+ # convention for that ; `Naming.snake` alone used to leave a
30
+ # creating command's bare name claiming the exact spelling a
31
+ # QUERY of the SAME business name also wants (`Account`'s own
32
+ # "Open" — the creating command AND a query listing open
33
+ # accounts, a real same-aggregate collision this corpus already
34
+ # has) — the suffix is what makes both nameable at all, not
35
+ # merely a style choice.
36
+ ir.commands.select(&:creates?).each do |command|
37
+ door.define_singleton_method("#{Naming.snake(command.hecks_name)}!") do |**args|
38
+ Handle.new(dispatcher: dispatcher, domain: domain, ir: ir,
39
+ instance: dispatcher.dispatch("#{fqn}.#{command.hecks_name}", with: args).instance)
40
+ end
41
+ end
42
+
43
+ # A query is a MODULE method too — same level as a creating
44
+ # command, since neither needs an existing record in hand — but
45
+ # bare: a query reads and returns, nothing to warn a caller
46
+ # about the way `!` does for a command. Answers the raw row
47
+ # array `dispatcher.query` itself answers, the same shape
48
+ # `runtime.query("#{fqn}.Name")` already gave.
49
+ ir.queries.each do |query|
50
+ door.define_singleton_method(Naming.snake(query.hecks_name)) do |**args|
51
+ dispatcher.query("#{fqn}.#{query.hecks_name}", **args)
52
+ end
53
+ end
54
+
55
+ door.define_singleton_method(:fqn) { fqn }
56
+ door.define_singleton_method(:ir) { ir }
57
+
58
+ # THE SAME VERB THE CHAPTER ANSWERS, one level down. Every
59
+ # construct emits its own IR (Hecks::IR), so an aggregate
60
+ # is a legitimate thing to project — `Pizzas::Order.project(
61
+ # Projections::IR)` is this aggregate's IR, not the chapter's.
62
+ #
63
+ # A chapter-scoped target refuses here rather than inventing an
64
+ # answer: `Projector.admits!` is what tells `Projections::IR`
65
+ # (`from: :any`) apart from `Projections::Shape`
66
+ # (`from: :chapter`), which used to return a confidently empty
67
+ # `{"aggregates" => []}` for an aggregate.
68
+ door.define_singleton_method(:project) do |target, out: nil, **options|
69
+ key = Projector.key_for(target)
70
+ artifact = Projector.call(key, bluebook: ir, options: options)
71
+ return artifact unless out
72
+
73
+ Projector.write(artifact, out, as: Projector.emits_for(key))
74
+ end
75
+ door.define_singleton_method(:repository) { dispatcher.registry.repository(domain, ir) }
76
+ door.define_singleton_method(:commands) { ir.commands.map { |c| "#{Naming.snake(c.hecks_name)}!" }.sort }
77
+ door.define_singleton_method(:queries) { ir.queries.map { |q| Naming.snake(q.hecks_name) }.sort }
78
+ # ONE AGGREGATE'S USAGE DOCUMENT — the same projection the chapter
79
+ # answers with, narrowed to this head. `commands` above already
80
+ # answers "what can I call"; this answers "and what does each one
81
+ # want, refuse, and guarantee", which is the rest of the question.
82
+ door.define_singleton_method(:docs) do |**options|
83
+ Projector.call(:docs, bluebook: dispatcher.registry.bluebook(domain),
84
+ options: options.merge(aggregate: ir.hecks_name))
85
+ end
86
+ # ONE AGGREGATE, READ BACK IN ENGLISH — the same narrowing `:docs`
87
+ # takes, aimed at `:narrate` instead.
88
+ door.define_singleton_method(:narrate) do |**options|
89
+ Projector.call(:narrate, bluebook: dispatcher.registry.bluebook(domain),
90
+ options: options.merge(aggregate: ir.hecks_name))
91
+ end
92
+ door.define_singleton_method(:count) { dispatcher.registry.repository(domain, ir).count }
93
+ door.define_singleton_method(:events) { dispatcher.events.select { |event| event.aggregate == fqn } }
94
+
95
+ door.define_singleton_method(:find) do |id|
96
+ found = dispatcher.registry.repository(domain, ir).find(id)
97
+ found && Handle.new(dispatcher: dispatcher, domain: domain, ir: ir, instance: found)
98
+ end
99
+
100
+ door.define_singleton_method(:all) do |**opts|
101
+ dispatcher.registry.repository(domain, ir).all(**opts).map do |instance|
102
+ Handle.new(dispatcher: dispatcher, domain: domain, ir: ir, instance: instance)
103
+ end
104
+ end
105
+
106
+ # THE SAME REASON `method_missing` BELOW EXISTS AT ALL — a facade
107
+ # left over from a PREVIOUS boot in this process shadows the fresh
108
+ # `BindingProxy` a `.hecksagon` would otherwise reach through
109
+ # `ConstShim`/`const_missing`, so `Pizzas::Pizza.port(...)` lands
110
+ # HERE instead once any boot has run before.
111
+ #
112
+ # RE-RESOLVED, NOT THE CLOSED-OVER `ir` — this door can be a STALE
113
+ # one, built by a boot from earlier in this same process, sitting
114
+ # on the `Pizzas`/`Pizza` constants only because nothing has
115
+ # re-installed them since. Attaching to this door's OWN `ir` would
116
+ # attach the port to a discarded aggregate from that old boot,
117
+ # invisible to the CURRENT one actually being loaded — silently,
118
+ # the exact way `method_missing` below already has to avoid it for
119
+ # a plain bind, via `HecksagonBuilder.collector` rather than
120
+ # anything this door closes over. `Hecks.current_registry` is
121
+ # the same "whichever boot is actually in progress" indirection,
122
+ # and `BindingProxy#port` already re-resolves through it the same
123
+ # way — this is that door's fallback twin, not a shortcut past it.
124
+ door.define_singleton_method(:port) do |name, &block|
125
+ current = Hecks.current_registry&.bluebook(domain)&.aggregate(ir.hecks_name) or
126
+ raise Bluebook::DSL::Malformed, "#{fqn}.port(#{name.inspect}) called outside a boot"
127
+
128
+ domain_port = Bluebook::DSL::ConstShim.with(->(const) { const }) do
129
+ Bluebook::DSL::DomainPortBuilder.build(name, owner: current.hecks_name, &block)
130
+ end
131
+ domain_port.operations.each do |operation|
132
+ operation.attributes.select(&:reference?).each { |attribute| attribute.type.declared_in = current }
133
+ end
134
+ current.add_port(domain_port)
135
+ self
136
+ end
137
+
138
+ door.define_singleton_method(:method_missing) do |verb, *args, **kwargs, &block|
139
+ collector = Bluebook::DSL::HecksagonBuilder.collector
140
+ return super(verb, *args, **kwargs, &block) unless collector
141
+
142
+ collector << Bluebook::Bind.new(
143
+ aggregate: fqn,
144
+ verb: verb.to_s,
145
+ adapter: args.first.to_s,
146
+ role: kwargs[:role]&.to_s
147
+ )
148
+ block&.call
149
+ self
150
+ end
151
+
152
+ door.define_singleton_method(:respond_to_missing?) do |name, include_private = false|
153
+ !Bluebook::DSL::HecksagonBuilder.collector.nil? || super(name, include_private)
154
+ end
155
+
156
+ # THE SAME STALE-FACADE HAZARD `method_missing`/`port` ABOVE ALREADY
157
+ # DOCUMENT, one door lower — `Surface.install` installs an aggregate's
158
+ # OWN name as a bare TOP-LEVEL constant too (`Namespace.install(Object,
159
+ # aggregate.hecks_name, ...)`, surface.rb's own `install`), not only
160
+ # nested under its chapter. So once ANY domain has booted once in this
161
+ # process, `Account::Debit` written while declaring some OTHER
162
+ # bluebook — same domain or a different one — reaches THIS door's
163
+ # const_missing directly, never `Object.const_missing`/`ConstShim::
164
+ # Hook` at all: real modules resolve without ever calling that.
165
+ #
166
+ # `ir.hecks_name`, NOT the qualified `fqn` — a scoped reference has to
167
+ # read the SAME either way, whether or not a stale door happens to be
168
+ # sitting on this process from an earlier boot; qualifying it here
169
+ # would make `Account::Debit`'s own meaning depend on incidental
170
+ # process history, which is the exact instability S0b exists to
171
+ # remove (docs/dsl-work-slices.md — "two domains in one registry" is
172
+ # this file's own reason for being owned by that slice).
173
+ door.define_singleton_method(:const_missing) do |name|
174
+ resolver = Bluebook::DSL::ConstShim.resolver
175
+ return resolver.call("#{ir.hecks_name}::#{name}") if resolver
176
+
177
+ super(name)
178
+ end
179
+
180
+ door
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,107 @@
1
+ require_relative "../../bluebook/dsl/binding_proxy"
2
+ require_relative "../../bluebook/dsl/const_shim"
3
+ require_relative "../../bluebook/dsl/hecksagon_builder"
4
+
5
+ module Hecks
6
+ module Facade
7
+ module Surface
8
+ # One chapter's module: vision and aggregate roll-call on the
9
+ # singleton, one aggregate door per declared head, and the
10
+ # declaration hook for names the door does not carry.
11
+ module Chapter
12
+ def chapter_module(dispatcher, bluebook)
13
+ chapter = Module.new
14
+ chapter.define_singleton_method(:vision) { bluebook.vision }
15
+ chapter.define_singleton_method(:aggregates) { bluebook.aggregates.map(&:name).sort }
16
+
17
+ # THE CHAPTER, EXPLAINING ITSELF. `Projector::DocsProjector` reads
18
+ # nothing but this bluebook's own IR, so the document cannot drift
19
+ # from the domain — the same guarantee `bin/reference` gives the DSL
20
+ # reference by generating it from the Syntax chapter.
21
+ #
22
+ # A METHOD RATHER THAN ONLY A SCRIPT because that is what gets it
23
+ # read: `QualityControl.docs` in a console, beside `vision` and
24
+ # `aggregates`, at the moment somebody is wondering what a verb
25
+ # wants. Projected on each call rather than memoised — it is a pure
26
+ # read of the IR, and a stale document is the entire thing this
27
+ # exists to prevent.
28
+ chapter.define_singleton_method(:docs) do |**options|
29
+ Projector.call(:docs, bluebook: bluebook, options: options)
30
+ end
31
+
32
+ # THE CHAPTER, READ BACK IN ENGLISH — `Projector::NarrateProjector`
33
+ # beside `:docs`, for the reader who needs to confirm the domain is
34
+ # right rather than call it: `QualityControl.narrate` in a console.
35
+ chapter.define_singleton_method(:narrate) do |**options|
36
+ Projector.call(:narrate, bluebook: bluebook, options: options)
37
+ end
38
+
39
+ # THE DOMAIN'S OWN IR, PROJECTED. `Projector` has taken
40
+ # `call(name, bluebook:, options:)` since §30, but nothing could
41
+ # reach it from a booted domain — this module already closes
42
+ # over the one `Bluebook` every projector wants and simply
43
+ # never handed it out, so every bin/ projector rebuilt a
44
+ # Registry and reloaded the files to recover what was already
45
+ # sitting here.
46
+ #
47
+ # Pizzas.project(Projections::OIDC)
48
+ # Pizzas.project(Projections::Shape, out: "shape.json")
49
+ #
50
+ # No `to_ir` companion: `project(Projections::IR)` already
51
+ # answers with the canonical serialized form, and handing out
52
+ # the live graph as well would be a second way to say the same
53
+ # thing. Anything genuinely needing the graph is a projector,
54
+ # and a projector is given it.
55
+ #
56
+ # `out:` writes and everything else is passed through to the
57
+ # target — so `options` stays the projector's own vocabulary
58
+ # (`audience:` for OIDC) rather than a fixed set this method
59
+ # would have to know about.
60
+ chapter.define_singleton_method(:project) do |target, out: nil, **options|
61
+ key = Projector.key_for(target)
62
+ artifact = Projector.call(key, bluebook: bluebook, options: options)
63
+ return artifact unless out
64
+
65
+ Projector.write(artifact, out, as: Projector.emits_for(key))
66
+ end
67
+
68
+ bluebook.aggregates.each do |aggregate|
69
+ chapter.const_set(aggregate.hecks_name, aggregate_module(dispatcher, bluebook.name, aggregate))
70
+ end
71
+
72
+ # INSIDE A HECKSAGON, A NAME IS A DECLARATION, NOT A LOOKUP. A
73
+ # `.hecksagon` may name an aggregate this door does not carry — a STALE
74
+ # door from an earlier boot resolving another registry's chapter, the
75
+ # exact hazard the constant tree used to hide by reinstalling on every
76
+ # load. With a collector open, the name becomes a `BindingProxy`
77
+ # recording the same bind the aggregate module would ; without one, it
78
+ # is a genuine NameError, exactly as before.
79
+ #
80
+ # THE OTHER READER OF A MISS is S0b's own bridge (docs/dsl-work-
81
+ # slices.md, const_shim.rb's `ScopedConstant`): a bluebook still being
82
+ # DECLARED that names `#{bluebook.name}::Something` — an event, a
83
+ # command reference, an `admits:` — reaches HERE, not
84
+ # `Object.const_missing`, the moment this chapter's own facade already
85
+ # exists (a previous boot in the same process, or this same chapter
86
+ # re-entering its own name). `ConstShim.active?` is exactly as true
87
+ # here as it is at the top level, mid-declaration, and consulting the
88
+ # SAME resolver is what makes a scoped reference resolve identically
89
+ # whether or not a facade happens to be built yet — the earlier
90
+ # attempt's own failure mode (this file's own history) was a bridge
91
+ # that worked only BEFORE any facade existed.
92
+ chapter.define_singleton_method(:const_missing) do |name|
93
+ collector = Bluebook::DSL::HecksagonBuilder.collector
94
+ return Bluebook::DSL::BindingProxy.new("#{bluebook.name}::#{name}", collector) if collector
95
+
96
+ resolver = Bluebook::DSL::ConstShim.resolver
97
+ return resolver.call("#{bluebook.name}::#{name}") if resolver
98
+
99
+ super(name)
100
+ end
101
+
102
+ chapter
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end
@@ -0,0 +1,48 @@
1
+ require_relative "surface/chapter"
2
+ require_relative "surface/aggregate_door"
3
+
4
+ module Hecks
5
+ module Facade
6
+ # THE DOOR, WITHOUT THE CLASSES.
7
+ #
8
+ # `Pizzas::Pizza.create_pizza(...)` is the public surface (HANDOVER rule 3),
9
+ # and this is what serves it now : anonymous per-boot modules whose
10
+ # singleton methods close over the dispatcher and dispatch by FQN — the
11
+ # same shape `Router::NamespaceInstaller` proved. Nothing here is a domain
12
+ # class ; the IR is the only graph, and the door is a projection of it,
13
+ # installed by `Loader.bind_runtime` and re-installed whole on the next
14
+ # boot. How a chapter's module is built is surface/chapter.rb; how one
15
+ # aggregate's door is built is surface/aggregate_door.rb.
16
+ #
17
+ # The hexagon-binding door rides along : `Pizzas::Pizza.persisted_by("Heki")`
18
+ # in a `.hecksagon` file lands on the module's `method_missing`, which
19
+ # records an `Bind` into whatever `HecksagonBuilder.collector` is open
20
+ # AT CALL TIME — so even a facade left over from a previous boot records
21
+ # into the current builder, and a chapter with no constant at all falls
22
+ # through to `ConstShim` → `BindingProxy`, which mints byte-identical binds.
23
+ module Surface
24
+ # These would shadow the machinery a Handle runs on, so a field named one
25
+ # of them gets no reader and says so — the same warning the class door gave.
26
+ RESERVED = %i[id state events reload inspect to_h hash class].freeze
27
+
28
+ extend Chapter
29
+ extend AggregateDoor
30
+
31
+ module_function
32
+
33
+ def install(dispatcher)
34
+ dispatcher.registry.bluebooks.each_value do |bluebook|
35
+ chapter = chapter_module(dispatcher, bluebook)
36
+ Namespace.install(Object, bluebook.name, chapter)
37
+
38
+ bluebook.aggregates.each do |aggregate|
39
+ next if aggregate.hecks_name == bluebook.name
40
+
41
+ Namespace.install(Object, aggregate.hecks_name, chapter.const_get(aggregate.hecks_name, false))
42
+ end
43
+ end
44
+ dispatcher
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,44 @@
1
+ module Hecks
2
+ # The class-free public surface — see facade/surface.rb for the door and
3
+ # facade/handle.rb for the record in hand. Installed per boot by
4
+ # `Runtime::Loader.bind_runtime`.
5
+ module Facade
6
+ end
7
+
8
+ # The one careful way to put something at top level.
9
+ #
10
+ # Overwrites only what it itself installed (tracked in GENERATED), refuses —
11
+ # with a warning, never a raise — to clobber a constant belonging to user
12
+ # code or the stdlib. Which is why a chapter named `Set` never becomes a
13
+ # constant, and why `Registry` keeps its own table of chapters rather than
14
+ # trusting Ruby's. Each re-install REPLACES the previous boot's entry, so
15
+ # what GENERATED retains is one small facade module per name, not a graph
16
+ # per boot.
17
+ module Namespace
18
+ GENERATED = {}
19
+
20
+ module_function
21
+
22
+ def install(container, name, value)
23
+ name = name.to_s
24
+
25
+ if container.const_defined?(name, false)
26
+ current = container.const_get(name)
27
+ unless GENERATED[[container, name]].equal?(current)
28
+ warn "[hecks] #{name} is already defined — leaving it alone"
29
+ return current
30
+ end
31
+ container.send(:remove_const, name)
32
+ end
33
+
34
+ container.const_set(name, value)
35
+ GENERATED[[container, name]] = value
36
+ value
37
+ end
38
+ end
39
+ end
40
+
41
+ require_relative "facade/handle"
42
+ require_relative "facade/surface"
43
+ require_relative "facade/command_request"
44
+ require_relative "facade/json_door"