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,364 @@
1
+ Hecks.bluebook "Bluebook" do
2
+ aggregate "Vocabulary" do
3
+ # These are DECLARATIONS, not runtime state — a language's admitted sets are
4
+ # fixed when the language is defined, which is what one_of means. They carry
5
+ # no commands on purpose : nothing dispatches a vocabulary, the conformance
6
+ # check READS them from the IR and holds the runtime's hand-typed tables to them.
7
+ #
8
+ # Every one of these is a set the runtime must agree with, and every one has
9
+ # already drifted or leaked at least once :
10
+ # Comparison went disjoint from the grammar chapter's operator table
11
+ # NormalisationStrategy is the third, unchecked copy of the canonical-form table
12
+ # Primitive is what "primitives live in value objects only" is ABOUT
13
+ # DomainRefusal is the boundary three raw Ruby TypeErrors crossed tonight
14
+ description "The closed sets the language admits — the whole of what any runtime may accept, declared once."
15
+
16
+ # ITS NAME, and nothing else. A vocabulary hangs under no other thing — the
17
+ # closed sets are the language's own, declared once — so one path is the whole
18
+ # identity.
19
+ identified_by VocabularyName, as: :name
20
+
21
+
22
+ value_object "VocabularyName" do
23
+ attribute :value, String
24
+ invariant("a vocabulary is named") { !value.to_s.empty? }
25
+ end
26
+
27
+ # Expression::Evaluator::COMPARISONS — six operators, all reduced by the
28
+ # evaluator to two primitives (less_than, equal) combined with a small boolean
29
+ # algebra: compares_less_than and compares_equal choose which primitive(s) OR
30
+ # together, negated inverts the result. `compare` reads this table instead of
31
+ # hardcoding a six-way case statement — see Evaluator::COMPARISONS.
32
+ value_object "Comparison" do
33
+ attribute :symbol, String
34
+ attribute :compares_less_than, String
35
+ attribute :compares_equal, String
36
+ attribute :negated, String
37
+
38
+ member symbol: ">=", compares_less_than: "true", compares_equal: "false", negated: "true"
39
+ member symbol: "<=", compares_less_than: "true", compares_equal: "true", negated: "false"
40
+ member symbol: "<", compares_less_than: "true", compares_equal: "false", negated: "false"
41
+ member symbol: ">", compares_less_than: "true", compares_equal: "true", negated: "true"
42
+ member symbol: "==", compares_less_than: "false", compares_equal: "true", negated: "false"
43
+ member symbol: "!=", compares_less_than: "false", compares_equal: "true", negated: "true"
44
+ end
45
+
46
+ # Expression::Resolver::SIGN_TESTS
47
+ # Each sign test is comparing against the literal 0, using an operator
48
+ # Comparison already declares — compares_via names which one, so a sign
49
+ # test is sugar for an existing operator rather than a second algebra
50
+ # beside it. `positive?` = value > 0, `negative?` = value < 0, `zero?` =
51
+ # value == 0.
52
+ value_object "SignTest" do
53
+ attribute :name, String
54
+ attribute :compares_via, String
55
+
56
+ member name: "positive?", compares_via: ">"
57
+ member name: "negative?", compares_via: "<"
58
+ member name: "zero?", compares_via: "=="
59
+ end
60
+
61
+ # `.include?`'s haystack type decides its behaviour : Array does
62
+ # membership (the same equal? primitive Comparison's == uses), String
63
+ # does an exact substring match and refuses a non-String needle. Anything
64
+ # else is always false — not declared here, since it is the fallback
65
+ # every OTHER haystack type shares, not a case of its own.
66
+ value_object "IncludeHaystack" do
67
+ attribute :type, String
68
+ attribute :strategy, String
69
+
70
+ member type: "Array", strategy: "membership"
71
+ member type: "String", strategy: "substring"
72
+ end
73
+
74
+ # `.to_s` admits exactly these scalar types, and every one of them uses
75
+ # the SAME rule (Ruby's own to_s — nil renders "", a bool its name, a
76
+ # number its digits, a string itself) — a closed set to admit into, not a
77
+ # table of different rules per type.
78
+ value_object "ToStringType" do
79
+ attribute :type, String, one_of: ["String", "Integer", "Float", "TrueClass", "FalseClass", "NilClass"]
80
+ end
81
+
82
+ # `.size` and `.empty?` admit exactly the same closed set — a list, a
83
+ # string, or an open map — and each just calls the one Ruby method
84
+ # already named for it. One declaration for both, since the set itself is
85
+ # the only thing either needed to say.
86
+ value_object "SizedType" do
87
+ attribute :type, String, one_of: ["Array", "String", "Hash"]
88
+ end
89
+
90
+ # Attribute::PRIMITIVES — the scalars a value object may bottom out in
91
+ value_object "Primitive" do
92
+ attribute :name, String, one_of: ["String", "Integer", "Float", "TrueClass", "FalseClass"]
93
+ end
94
+
95
+ # Expression::CanonicalForm::STRATEGIES
96
+ value_object "NormalisationStrategy" do
97
+ attribute :name, String, one_of: ["collapse_whitespace", "replace"]
98
+ end
99
+
100
+ # the ops Runtime::CommandInterpreter applies. `sign` is the arithmetic
101
+ # delta increment/decrement share one primitive by — CommandRules#arithmetic
102
+ # applies `current + sign *
103
+ # amount`, differing only in which sign. set and append do no arithmetic,
104
+ # so they carry no sign — ABSENT IS NOT EMPTY, same reading as elsewhere in
105
+ # this file.
106
+ value_object "MutationOp" do
107
+ attribute :name, String
108
+ attribute :sign, String
109
+
110
+ member name: "set", sign: ""
111
+ member name: "append", sign: ""
112
+ member name: "increment", sign: "1"
113
+ member name: "decrement", sign: "-1"
114
+ # Vendored addition, not (yet) upstream hecks (migration plan
115
+ # task 4, i106 in-DSL math — CommandRules::Arithmetic#multiply/
116
+ # #clamp): multiply scales (`current * amount`), clamp bounds
117
+ # (`current.clamp(min, max)`) — neither is an add/subtract, so
118
+ # neither carries a sign, same reading as set/append above.
119
+ member name: "multiply", sign: ""
120
+ member name: "clamp", sign: ""
121
+ # Vendored addition, not (yet) upstream hecks (migration plan
122
+ # task 4): remove — the list-removal counterpart to append,
123
+ # matching an element by value. No sign, same reading as append.
124
+ member name: "remove", sign: ""
125
+ # Vendored addition, not (yet) upstream hecks — CommandBuilder
126
+ # #delegates_to's own comment gives the full reasoning: an
127
+ # aggregate-level command's synchronous, single-dispatch handoff
128
+ # into one nested entity command, rather than a policy/saga's own
129
+ # commit-then-react reentry. Rides the SAME multi-binding wire
130
+ # shape append does (`with: {...}` is a field map, same as
131
+ # append's own `fields:`), so it carries no sign, same reading.
132
+ member name: "delegate", sign: ""
133
+ end
134
+
135
+ # QuerySpecification::Common::Comparators::COMPARATORS — a where-clause's
136
+ # admitted operators. Unlike Comparison, these do not reduce to one shared
137
+ # boolean algebra (eq/ne compare values, gt/gte/lt/lte order them, in/contains
138
+ # test membership in opposite directions), so this stays a flat closed set —
139
+ # the same shape MutationOp had before it grew a sign.
140
+ # `none_in_state` (the last member) is a vendored addition, not (yet)
141
+ # upstream hecks (migration plan task 4) — see
142
+ # query_specification/common/comparators.rb's own comment on
143
+ # none_in_state. Both closed sets (the Ruby COMPARATORS constant and
144
+ # this self-hosted grammar entry) must agree, the same two-places-
145
+ # must-agree discipline MutationOp/multiply/clamp already required
146
+ # earlier this pass.
147
+ value_object "QueryComparator" do
148
+ attribute :name, String, one_of: ["eq", "ne", "gt", "gte", "lt", "lte", "in", "contains", "none_in_state"]
149
+ end
150
+
151
+ # Adapters::Driven::Folder::DOMAIN_ORDER — declarations load in this order
152
+ value_object "LoadOrder" do
153
+ attribute :glob, String,
154
+ one_of: ["*.port", "*.adapter", "*.bluebook", "translations/*.bluebook", "*.hecksagon", "*.world"]
155
+ end
156
+
157
+ # CommandInterpreter#call — an aggregate command's
158
+ # own interpretation, ending at the events it emits. Reaction (policies,
159
+ # sagas) is a structurally separate phase and is not part
160
+ # of this : CommandInterpreter#call returns before it runs, in a
161
+ # different class — reaction is
162
+ # what a command's OWN emitted events cause, not what interpreting
163
+ # the command does. Two conditional steps — assign_creation_attributes only
164
+ # fires for a creating command, advance_lifecycle only when a transition
165
+ # applies — so this is the order a command that does both follows,
166
+ # confirmed by tracing a real dispatch, not read off the source.
167
+ value_object "AggregateDispatchOrder" do
168
+ attribute :step, String,
169
+ one_of: ["refuse_unknown_arguments", "refuse_absent_arguments", "normalize_args",
170
+ "refuse_role_mismatch", "resolve_references", "hydrate", "enforce_givens",
171
+ "admissible_transition", "assign_creation_attributes", "apply_mutations",
172
+ "advance_lifecycle", "delegate_to_entity", "enforce_ensures", "enforce_invariants",
173
+ "save", "emit"]
174
+ end
175
+
176
+ # EntityInterpreter#call — the same shape
177
+ # one level down, on a piece an aggregate holds rather than the aggregate
178
+ # itself. Shorter than AggregateDispatchOrder because an entity is never
179
+ # CREATED through this path (no assign_creation_attributes) and inherits
180
+ # its aggregate's own argument gate rather than running one of its own (no
181
+ # refuse_unknown_arguments) — hydrating the parent and locating the
182
+ # element replace a single hydrate. resolve_references stayed, though —
183
+ # an entity command can declare a reference-typed attribute the same way
184
+ # an aggregate command can (CommandRules#resolve_references is shared by
185
+ # both interpreters), even though nothing in the real corpus does yet.
186
+ value_object "EntityDispatchOrder" do
187
+ attribute :step, String,
188
+ one_of: ["normalize_args", "refuse_role_mismatch", "resolve_references", "hydrate_parent",
189
+ "locate_element", "enforce_givens", "admissible_transition", "apply_mutations",
190
+ "advance_lifecycle", "enforce_ensures", "enforce_invariants", "save", "emit"]
191
+ end
192
+
193
+ # Runtime::Errors::DOMAIN_REFUSALS — what counts as the domain judging,
194
+ # as opposed to the runtime breaking. Anything outside this set that reaches
195
+ # a refusal list is a bug wearing a refusal's clothes.
196
+ value_object "DomainRefusal" do
197
+ attribute :name, String,
198
+ one_of: ["AbsentArgument", "AlreadyExists", "AttributeAbsent", "EnsuresNotMet", "GivenNotMet",
199
+ "InvariantViolation", "LifecycleRefused", "NotFound", "ProjectionAbsent", "RemoteRefusal",
200
+ "TypeMismatch", "Unauthorized", "UnknownArgument", "UnknownVerb"]
201
+ end
202
+
203
+ # THE WORDING ITSELF, for every DomainRefusal site that is not already
204
+ # data — `given`/`ensures`/a declared `invariant` already carry their own
205
+ # description, read at dispatch time off the command or value object that
206
+ # declared them. Everything here is different in kind: a LANGUAGE-LEVEL
207
+ # refusal, the same wording for every domain, not authored per-bluebook —
208
+ # closer to Comparison/SignTest beside it than to a given. So it follows
209
+ # THEIR pattern, not given's: declared here for a human to read and a
210
+ # conformance spec to hold equal, and a hand-typed table
211
+ # (RefusalWording) is what a dispatch
212
+ # actually reads — the same reason Evaluator::SIGN_TEST_OPERATORS is
213
+ # hand-typed rather than read live off this very chapter at every call.
214
+ #
215
+ # `{name}` markers are placeholders — plain text substitution, not
216
+ # expression syntax ; a template is read, never evaluated. Two call
217
+ # sites that happen to raise the same sentence share one `site` row
218
+ # (entity_interpreter.rb and command_interpreter.rb's own "not found"
219
+ # messages, for instance) rather than being declared as two facts that
220
+ # would have to be kept identical by hand.
221
+ value_object "RefusalTemplate" do
222
+ attribute :refusal, String, admits: "Vocabulary::DomainRefusal"
223
+ attribute :site, String
224
+ attribute :template, String
225
+
226
+ member refusal: "NotFound", site: "creating_no_identity",
227
+ template: "{command} creates a {aggregate} — pass {identity}:"
228
+ member refusal: "AlreadyExists", site: "creating_duplicate",
229
+ template: "{command} creates a {aggregate} that already exists — {identity} {offered}"
230
+ member refusal: "AlreadyExists", site: "entity_duplicate",
231
+ template: "a {entity} already exists on {aggregate} — {identity} {offered}"
232
+ member refusal: "NotFound", site: "acting_no_identity",
233
+ template: "{command} acts on an existing {aggregate} — pass {identity}:"
234
+ member refusal: "NotFound", site: "record_missing",
235
+ template: "no {aggregate} with {identity} {offered}"
236
+ member refusal: "NotFound", site: "entity_parent_no_identity",
237
+ template: "{command} acts on a {aggregate}'s {entity} — pass {identity}:"
238
+ member refusal: "UnknownVerb", site: "entity_unknown",
239
+ template: "{aggregate} has no entity {entity}"
240
+ member refusal: "NotFound", site: "entity_element_no_identity",
241
+ template: "{command} acts on one {entity} — pass {identity}:"
242
+ member refusal: "NotFound", site: "entity_element_missing",
243
+ template: "no {entity} with {identity} {wants} on {aggregate} {parent_id}"
244
+ member refusal: "NotFound", site: "reference_target_missing",
245
+ template: "no {target} with {heads} {key}"
246
+ member refusal: "NotFound", site: "read_model_reference_missing",
247
+ template: "no {aggregate} with reference {offered}"
248
+ member refusal: "TypeMismatch", site: "read_model_object_reference",
249
+ template: "{query} refused — a reference is an id, and {field} arrived as an object"
250
+ member refusal: "UnknownVerb", site: "no_query",
251
+ template: "{aggregate} has no query {query}"
252
+ member refusal: "UnknownVerb", site: "entity_query_missing",
253
+ template: "{entity} has no query {query}"
254
+ member refusal: "UnknownVerb", site: "entity_holds_no_list",
255
+ template: "{aggregate} holds no list of {entity}"
256
+ member refusal: "UnknownVerb", site: "entity_no_command",
257
+ template: "{entity} has no command {command}"
258
+ member refusal: "UnknownVerb", site: "aggregate_no_command",
259
+ template: "{aggregate} has no command {command}"
260
+ member refusal: "UnknownVerb", site: "port_no_operation",
261
+ template: "{port} has no operation {operation}"
262
+ member refusal: "UnknownVerb", site: "no_domain",
263
+ template: "no domain {domain} loaded (verb {verb})"
264
+ member refusal: "UnknownVerb", site: "no_read_model",
265
+ template: "{domain} has no read model {query}"
266
+ member refusal: "UnknownVerb", site: "not_fully_qualified",
267
+ template: "{verb} is not a fully-qualified verb (Domain::Aggregate.Command)"
268
+ member refusal: "UnknownVerb", site: "no_aggregate",
269
+ template: "{domain} has no aggregate {aggregate}"
270
+ member refusal: "LifecycleRefused", site: "transition_blocked",
271
+ template: "{command} refused — {field} is {current}, and {command} moves it only from {allowed}"
272
+ member refusal: "TypeMismatch", site: "value_object_shape",
273
+ template: "{name} is a {type} — pass its fields as an object, not {offered}"
274
+ member refusal: "TypeMismatch", site: "reference_as_object",
275
+ template: "{command} refused — a reference is an id, and {attribute} arrived as an object{known_by}"
276
+ member refusal: "TypeMismatch", site: "multi_field_scalar",
277
+ template: "{type} has multiple fields and cannot stand in for a scalar"
278
+ member refusal: "TypeMismatch", site: "composite_identity",
279
+ template: "{type} is a composite identity — an identity must have exactly one field"
280
+ member refusal: "TypeMismatch", site: "numeric_field",
281
+ template: "{type}.{field} expects {expected}, got {offered}"
282
+ member refusal: "TypeMismatch", site: "pattern_mismatch",
283
+ template: "{type}.{field} must match {pattern}, got {offered}"
284
+ member refusal: "TypeMismatch", site: "arithmetic_amount",
285
+ template: "{op} of {target} needs an Integer, got {offered}"
286
+ member refusal: "TypeMismatch", site: "arithmetic_current",
287
+ template: "{op} of {target} needs an Integer {target}, got {offered}"
288
+ member refusal: "TypeMismatch", site: "arithmetic_shared_field",
289
+ template: "{op} of {target} needs a value object with one shared Integer field"
290
+ member refusal: "UnknownArgument", site: "unknown_args",
291
+ template: "{command} does not declare {unknown} — it takes {declared}"
292
+ member refusal: "AbsentArgument", site: "absent_args",
293
+ template: "{command} was not given {absent} — it takes {declared}"
294
+ member refusal: "InvariantViolation", site: "closed_set_member",
295
+ template: "{type} admits {admitted} — got {offered}"
296
+ member refusal: "InvariantViolation", site: "value_object_invariant",
297
+ template: "{name} invariant violated — {description} (given {offered})"
298
+ member refusal: "InvariantViolation", site: "admits_declared_set",
299
+ template: "{name} admits {admits} — {admitted} — got {offered}"
300
+ member refusal: "InvariantViolation", site: "undeclared_set",
301
+ template: "{name} admits {admits}, which this chapter does not declare — a closed set is named " \
302
+ "Aggregate::SetName, and it must be one the bluebook actually holds"
303
+ member refusal: "Unauthorized", site: "tenant_required",
304
+ template: "{query} declares authorize with tenant: {field} — pass {field}: to name which " \
305
+ "{field} this ask is scoped to"
306
+ member refusal: "Unauthorized", site: "role_mismatch",
307
+ template: "{command} refused — role: {role}, and the caller stated {caller_role}"
308
+ member refusal: "AttributeAbsent", site: "absent_read",
309
+ template: "{aggregate} {field} is absent on this record — declared, not optional, and " \
310
+ "added since it was written. Backfill it in a translation (backfill :{field}, " \
311
+ "default: ...), or declare it optional: true"
312
+ # S12, ADR 0025 — the same silent-wrong-answer class AttributeAbsent
313
+ # above refuses, one line up: a `projects` field this record predates,
314
+ # or that no rebuild sweep has populated yet, read by a rule as
315
+ # though it were a real value rather than one nobody has copied over.
316
+ member refusal: "ProjectionAbsent", site: "absent_read",
317
+ template: "{aggregate} {field} is not yet projected on this record — declared via " \
318
+ "projects :{field}, but no rebuild sweep has populated it. Run the sweep, " \
319
+ "or read {reference}.{remote_field} directly if this rule cannot wait"
320
+ end
321
+
322
+ # SagaInterpreter::REFUSED.
323
+ #
324
+ # A leg answers an EVENT — `on "AccountDebited"` — or it answers one of these,
325
+ # which are not events at all: no aggregate announces that a leg the procedure
326
+ # dispatched was declined. `on :refused` is the compensating leg, and without
327
+ # this declaration the word lived only as a magic string in the interpreter,
328
+ # and a reader of the language could not discover the
329
+ # trigger existed.
330
+ value_object "Trigger" do
331
+ attribute :name, String, one_of: ["refused"]
332
+ end
333
+
334
+ # Hecks::Forms::FieldShape's own EMAIL_HINT/URL_HINT/
335
+ # TEL_HINT/TEXTAREA_HINT (lib/hecks/forms/field_shape.rb)
336
+ # — the regexes `text_field` matches a text attribute's own NAME
337
+ # against (case-insensitively) to guess an HTML input type or a
338
+ # textarea kind, when nothing more specific (a `pattern:`, an
339
+ # `admits:`, a closed set) already answered the question. Declared
340
+ # here for the same reason RefusalTemplate is: a LANGUAGE-LEVEL
341
+ # rendering convention, the same guess for every domain, not
342
+ # authored per-bluebook — closer to Comparison/SignTest than to a
343
+ # given. `pattern` is the regex SOURCE, no delimiters or flags
344
+ # (Ruby's own `Regexp#source`) — spec/field_hint_conformance_spec.rb
345
+ # holds FieldShape's four hand-typed constants equal to this, both
346
+ # directions, the same conformance shape refusal_wording_
347
+ # conformance_spec.rb already holds RefusalTemplate to.
348
+ #
349
+ # `resolves_to` names WHICH Field attribute a match sets — `html_type`
350
+ # for email/url/tel (three candidates, only one wins, checked in that
351
+ # order), `kind` for textarea (checked separately, and only once
352
+ # html_type has already fallen through to "text").
353
+ value_object "FieldHint" do
354
+ attribute :name, String
355
+ attribute :pattern, String
356
+ attribute :resolves_to, String
357
+
358
+ member name: "email", pattern: 'email', resolves_to: "html_type"
359
+ member name: "url", pattern: '\b(url|uri|website|link)\b', resolves_to: "html_type"
360
+ member name: "tel", pattern: 'phone|\btel(ephone)?\b', resolves_to: "html_type"
361
+ member name: "textarea", pattern: '\b(text|body|note|notes|description|message|comment)\b', resolves_to: "kind"
362
+ end
363
+ end
364
+ end
@@ -0,0 +1,51 @@
1
+ Hecks.bluebook "Hecksagon" do
2
+ aggregate "AdapterBinding" do
3
+ description "One aggregate-to-adapter binding inside a hecksagon — the verb it answers, the adapter it names. Its own root because a hecksagon's binds are an open set of verbs (one per declared port), which no value object can hold — the same reasoning Wiring carries for a world's settings."
4
+
5
+ # The retained parent edge is structural state. `hecksagon` below is
6
+ # separately the text component of this binding's own compound identity,
7
+ # so the relationship keeps the same explicit `_ref` distinction World::
8
+ # Wiring uses for its parent edge.
9
+ belongs_to Hecksagon, as: :hecksagon_ref
10
+
11
+ # THE HECKSAGON IT IS IN, THE AGGREGATE IT NAMES, THE VERB IT ANSWERS.
12
+ # One hecksagon binds one adapter per (aggregate, verb) pair — that is
13
+ # what a binding IS — so the triple identifies it.
14
+ identified_by :hecksagon, :aggregate, :verb
15
+
16
+ attribute :hecksagon, BindingText
17
+ attribute :aggregate, BindingText
18
+ attribute :verb, BindingText
19
+ attribute :adapter, BindingText
20
+ attribute :role, BindingText, optional: true
21
+
22
+ value_object "BindingText" do
23
+ attribute :value, String
24
+ end
25
+
26
+ command "Bind" do
27
+ role "Deployment"
28
+ goal "Name the adapter one aggregate answers one verb through"
29
+
30
+ # A creating command receives the parent's identity as an ordinary
31
+ # value fact. It does not declare a behavioral relationship or use the
32
+ # parent as a hidden receiver.
33
+ attribute :hecksagon_ref, HecksagonName
34
+ attribute :aggregate, BindingText
35
+ attribute :verb, BindingText
36
+ attribute :adapter, BindingText
37
+ attribute :role, BindingText, optional: true
38
+
39
+ given("a binding names its verb") { !verb.value.to_s.empty? }
40
+
41
+ sets :hecksagon_ref
42
+ sets :hecksagon
43
+ sets :aggregate
44
+ sets :verb
45
+ sets :adapter
46
+ sets :role
47
+
48
+ emits "Bound"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,76 @@
1
+ Hecks.bluebook "Hecksagon" do
2
+ aggregate "DomainPort" do
3
+ description "A primary port — the boundary between a domain and its adapters, in hexagonal terms, is exactly what a hecksagon already IS for every other port. Root-level (belongs to the chapter) or aggregate-scoped (reached the same way persisted_by is, through the open Const.verb(...) door). One of two shapes, never both: a list of operations translating an inbound fact into this domain's own events, or a bare verb naming a swappable resource port (the same Hecks.port a project's own .port file declares, reached from inside the hecksagon instead)."
4
+
5
+ identified_by PortName, as: :name
6
+
7
+ attribute :verb, PortVerb, optional: true
8
+
9
+ value_object "PortName" do
10
+ attribute :value, String
11
+ invariant("a port is named") { !value.to_s.empty? }
12
+ end
13
+
14
+ value_object "PortVerb" do
15
+ attribute :value, String
16
+ invariant("a verb is named") { !value.to_s.empty? }
17
+ end
18
+
19
+ # HOW DOMAINPORT IS SPELLED. These rows live with the concept
20
+ # they describe; SyntaxBoot discovers every aggregate-local seed table.
21
+ # Contexts represented here: DomainPort.
22
+ value_object "KeywordSeed" do
23
+ attribute :word, String
24
+ attribute :context, String, admits: "Syntax::Context"
25
+ attribute :body, String, admits: "Syntax::Body"
26
+ attribute :inner, String
27
+ attribute :opens, String
28
+ attribute :fills, String
29
+ attribute :status, String, default: "admitted", admits: "Syntax::Status"
30
+ attribute :was, String
31
+ attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
32
+ attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
33
+
34
+ member word: "operation", context: "DomainPort", body: "keywords", inner: "PortOperation", opens: "PortOperation", fills: "", calls: "tells_impl"
35
+ member word: "tells", context: "DomainPort", body: "keywords", inner: "PortOperation", opens: "PortOperation", fills: "", calls: "tells_impl"
36
+ member word: "asks", context: "DomainPort", body: "keywords", inner: "PortOperation", opens: "PortOperation", fills: "", calls: "asks_impl"
37
+ member word: "verb", context: "DomainPort", body: "none", inner: "", opens: "", fills: "verb"
38
+
39
+ end
40
+
41
+ value_object "ArgumentSeed" do
42
+ attribute :keyword, String
43
+ attribute :context, String, admits: "Syntax::Context"
44
+ attribute :at, String
45
+ attribute :named, String
46
+ attribute :kind, String, admits: "Syntax::ArgumentKind"
47
+ attribute :required, String
48
+ attribute :fills, String
49
+ attribute :selects, String
50
+ attribute :pair_key_fills, String
51
+ attribute :pair_value_fills, String
52
+ attribute :pairs_shape, String, admits: "Syntax::PairsShape"
53
+ attribute :status, String, default: "admitted", admits: "Syntax::Status"
54
+ attribute :variadic, String
55
+ attribute :coerce, String
56
+ attribute :blank_message, String
57
+
58
+ member keyword: "operation", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "name"
59
+ member keyword: "tells", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "name"
60
+ member keyword: "asks", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "name"
61
+ member keyword: "verb", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "verb"
62
+
63
+ # THE RECEIVING AGGREGATE — PortOperationBuilder's own `reference_to`
64
+ # (inside the block) is refused (#335); this is the sanctioned
65
+ # replacement, named directly on the word that opens the block
66
+ # rather than a statement inside it. `kind: "constant"`, matching
67
+ # `reference_to`'s own first positional argument
68
+ # (port_operation.bluebook) — same bareword-constant resolution,
69
+ # just moved.
70
+ member keyword: "operation", context: "DomainPort", at: "", named: "to", kind: "constant", required: "false", fills: "to"
71
+ member keyword: "tells", context: "DomainPort", at: "", named: "to", kind: "constant", required: "false", fills: "to"
72
+ member keyword: "asks", context: "DomainPort", at: "", named: "to", kind: "constant", required: "false", fills: "to"
73
+
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,131 @@
1
+ Hecks.bluebook "Hecksagon" do
2
+ aggregate "Hecksagon" do
3
+ description "One .hecksagon — the events a domain subscribes to, and the root every binding hangs off. A sibling artifact to the bluebook, not part of it."
4
+
5
+ identified_by HecksagonName, as: :domain
6
+
7
+ attribute :subscriptions, list_of(Subscription)
8
+ attribute :framework_members, list_of(FrameworkMember)
9
+ attribute :vendored_bluebooks, list_of(VendoredBluebook)
10
+
11
+ value_object "HecksagonName" do
12
+ attribute :value, String
13
+ invariant("a hecksagon names its domain") { !value.to_s.empty? }
14
+ end
15
+
16
+ value_object "Subscription" do
17
+ attribute :value, String
18
+ invariant("a subscription names an event") { !value.to_s.empty? }
19
+ end
20
+
21
+ # A `framework/bluebook/` member this hecksagon attaches — Governance,
22
+ # Identity, whatever else lands beside them. Same shape as
23
+ # `Subscription` beside it, one word over.
24
+ value_object "FrameworkMember" do
25
+ attribute :value, String
26
+ invariant("a framework member is named") { !value.to_s.empty? }
27
+ end
28
+
29
+ # A vendored, external bluebook this hecksagon attaches — one level
30
+ # further out than `FrameworkMember`: not a member shipped inside
31
+ # hecks's own lib/, but a separate package vendored into the
32
+ # consuming project's own checkout. Same shape as `FrameworkMember`
33
+ # beside it, one word over — see EmbryonautBluebook's own header.
34
+ value_object "VendoredBluebook" do
35
+ attribute :value, String
36
+ invariant("a vendored bluebook is named") { !value.to_s.empty? }
37
+ end
38
+
39
+ command "Declare" do
40
+ role "Deployment"
41
+ goal "Open a hecksagon for a domain"
42
+
43
+ attribute :domain, HecksagonName
44
+
45
+ sets :domain
46
+
47
+ emits "HecksagonDeclared"
48
+ end
49
+
50
+ command "Subscribe" do
51
+ role "Deployment"
52
+ goal "Take a hecksagon's own event, from outside the domain's own bluebook"
53
+
54
+ attribute :event, Subscription
55
+
56
+ sets :subscriptions, append: { value: :event }
57
+
58
+ emits "SubscriptionAdded"
59
+ end
60
+
61
+ command "UsesFramework" do
62
+ role "Deployment"
63
+ goal "Attach a framework/bluebook/ member to this hecksagon"
64
+
65
+ attribute :member, FrameworkMember
66
+
67
+ sets :framework_members, append: { value: :member }
68
+
69
+ emits "FrameworkMemberAttached"
70
+ end
71
+
72
+ command "UsesEmbryonautBluebook" do
73
+ role "Deployment"
74
+ goal "Attach a vendored, external bluebook to this hecksagon"
75
+
76
+ attribute :package, VendoredBluebook
77
+
78
+ sets :vendored_bluebooks, append: { value: :package }
79
+
80
+ emits "VendoredBluebookAttached"
81
+ end
82
+
83
+ # HOW HECKSAGON IS SPELLED. These rows live with the concept
84
+ # they describe; SyntaxBoot discovers every aggregate-local seed table.
85
+ # Contexts represented here: File, Hecksagon.
86
+ value_object "KeywordSeed" do
87
+ attribute :word, String
88
+ attribute :context, String, admits: "Syntax::Context"
89
+ attribute :body, String, admits: "Syntax::Body"
90
+ attribute :inner, String
91
+ attribute :opens, String
92
+ attribute :fills, String
93
+ attribute :status, String, default: "admitted", admits: "Syntax::Status"
94
+ attribute :was, String
95
+ attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
96
+ attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
97
+
98
+ member word: "hecksagon", context: "File", body: "keywords", inner: "Hecksagon", opens: "Hecksagon", fills: ""
99
+ member word: "subscribe", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "subscriptions"
100
+ member word: "uses_framework", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "framework_members"
101
+ member word: "uses_embryonaut_bluebook", context: "Hecksagon", body: "none", inner: "", opens: "", fills: "vendored_bluebooks"
102
+ member word: "port", context: "Hecksagon", body: "keywords", inner: "DomainPort", opens: "DomainPort", fills: "", calls: "port_impl"
103
+
104
+ end
105
+
106
+ value_object "ArgumentSeed" do
107
+ attribute :keyword, String
108
+ attribute :context, String, admits: "Syntax::Context"
109
+ attribute :at, String
110
+ attribute :named, String
111
+ attribute :kind, String, admits: "Syntax::ArgumentKind"
112
+ attribute :required, String
113
+ attribute :fills, String
114
+ attribute :selects, String
115
+ attribute :pair_key_fills, String
116
+ attribute :pair_value_fills, String
117
+ attribute :pairs_shape, String, admits: "Syntax::PairsShape"
118
+ attribute :status, String, default: "admitted", admits: "Syntax::Status"
119
+ attribute :variadic, String
120
+ attribute :coerce, String
121
+ attribute :blank_message, String
122
+
123
+ member keyword: "hecksagon", context: "File", at: "1", named: "", kind: "text", required: "true", fills: "domain"
124
+ member keyword: "subscribe", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "subscriptions"
125
+ member keyword: "uses_framework", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "framework_members"
126
+ member keyword: "uses_embryonaut_bluebook", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "vendored_bluebooks"
127
+ member keyword: "port", context: "Hecksagon", at: "1", named: "", kind: "text", required: "true", fills: "name"
128
+
129
+ end
130
+ end
131
+ end