hecks 2.7.0 → 2.9.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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +11 -0
  3. data/lib/hecks/adapters/driven/claude_code.rb +4 -104
  4. data/lib/hecks/adapters/driven/d1.rb +44 -237
  5. data/lib/hecks/adapters/driven/folder.rb +17 -76
  6. data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
  7. data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
  8. data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
  9. data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
  10. data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
  11. data/lib/hecks/adapters/driven/heki.rb +13 -42
  12. data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
  13. data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
  14. data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
  15. data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
  16. data/lib/hecks/adapters/driven/lambda.rb +10 -84
  17. data/lib/hecks/adapters/driven/local_storage.rb +5 -40
  18. data/lib/hecks/adapters/driven/memory.rb +18 -99
  19. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
  20. data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
  21. data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
  22. data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
  23. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
  24. data/lib/hecks/adapters/driven/postgres.rb +145 -134
  25. data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
  26. data/lib/hecks/adapters/driven/prism.rb +7 -30
  27. data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
  28. data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
  29. data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
  30. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
  31. data/lib/hecks/adapters/driven/sqlite.rb +128 -65
  32. data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
  33. data/lib/hecks/adapters/driven.rb +5 -36
  34. data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
  35. data/lib/hecks/behaviors/dsl.rb +7 -25
  36. data/lib/hecks/behaviors/expectations.rb +32 -142
  37. data/lib/hecks/behaviors/ir.rb +7 -20
  38. data/lib/hecks/behaviors/rspec.rb +6 -17
  39. data/lib/hecks/behaviors/runner.rb +10 -34
  40. data/lib/hecks/behaviors.rb +4 -8
  41. data/lib/hecks/bluebook/aggregate.rb +9 -75
  42. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
  43. data/lib/hecks/bluebook/assembly/build.rb +4 -15
  44. data/lib/hecks/bluebook/assembly/contract.rb +15 -136
  45. data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
  46. data/lib/hecks/bluebook/assembly/marks.rb +31 -223
  47. data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
  48. data/lib/hecks/bluebook/assembly.rb +6 -45
  49. data/lib/hecks/bluebook/attribute.rb +12 -61
  50. data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
  51. data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
  52. data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
  53. data/lib/hecks/bluebook/behaviour/command.rb +14 -66
  54. data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
  55. data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
  56. data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
  57. data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
  58. data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
  59. data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
  60. data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
  61. data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
  62. data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
  63. data/lib/hecks/bluebook/capabilities.rb +17 -49
  64. data/lib/hecks/bluebook/chapter.rb +10 -48
  65. data/lib/hecks/bluebook/command.rb +23 -81
  66. data/lib/hecks/bluebook/domain_port.rb +14 -63
  67. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
  68. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
  69. data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
  70. data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
  71. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
  72. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
  73. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
  74. data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
  75. data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
  76. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
  77. data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
  78. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
  79. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
  80. data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
  81. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
  82. data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
  83. data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
  84. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
  85. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
  86. data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
  87. data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
  88. data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
  89. data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
  90. data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
  91. data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
  92. data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
  93. data/lib/hecks/bluebook/entity.rb +13 -71
  94. data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
  95. data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
  96. data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
  97. data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
  98. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
  99. data/lib/hecks/bluebook/expression/resolver.rb +37 -660
  100. data/lib/hecks/bluebook/hexagon.rb +5 -28
  101. data/lib/hecks/bluebook/lifecycle.rb +5 -16
  102. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
  103. data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
  104. data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
  105. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
  106. data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
  107. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
  108. data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
  109. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
  110. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
  111. data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
  112. data/lib/hecks/bluebook/meta_validator.rb +79 -349
  113. data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
  114. data/lib/hecks/bluebook/model_check.rb +102 -600
  115. data/lib/hecks/bluebook/pattern_subset.rb +11 -69
  116. data/lib/hecks/bluebook/process_manager.rb +13 -83
  117. data/lib/hecks/bluebook/project_loader.rb +3 -39
  118. data/lib/hecks/bluebook/project_register.rb +12 -60
  119. data/lib/hecks/bluebook/query.rb +9 -48
  120. data/lib/hecks/bluebook/read_model.rb +57 -81
  121. data/lib/hecks/bluebook/reference.rb +7 -41
  122. data/lib/hecks/bluebook/smoke_test.rb +8 -98
  123. data/lib/hecks/bluebook/synthesizer.rb +13 -62
  124. data/lib/hecks/bluebook/translation.rb +26 -62
  125. data/lib/hecks/bluebook/value_object.rb +11 -36
  126. data/lib/hecks/bluebook.rb +5 -22
  127. data/lib/hecks/cache_dir.rb +84 -0
  128. data/lib/hecks/cli/document.rb +86 -0
  129. data/lib/hecks/cli/ir.rb +45 -0
  130. data/lib/hecks/cli/mcp.rb +31 -0
  131. data/lib/hecks/cli/mcp_door.rb +366 -0
  132. data/lib/hecks/cli/model_check.rb +203 -0
  133. data/lib/hecks/cli/project_cli.rb +90 -0
  134. data/lib/hecks/cli/project_diagrams.rb +36 -0
  135. data/lib/hecks/cli/run.rb +173 -0
  136. data/lib/hecks/cli/smoke_test.rb +45 -0
  137. data/lib/hecks/cli/stores.rb +53 -0
  138. data/lib/hecks/cli.rb +160 -0
  139. data/lib/hecks/construct.rb +8 -34
  140. data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
  141. data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
  142. data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
  143. data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
  144. data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
  145. data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
  146. data/lib/hecks/embryonaut_bluebook.rb +4 -71
  147. data/lib/hecks/facade/cli_door.rb +24 -106
  148. data/lib/hecks/facade/cli_runner.rb +28 -172
  149. data/lib/hecks/facade/command_request.rb +13 -33
  150. data/lib/hecks/facade/handle.rb +34 -121
  151. data/lib/hecks/facade/json_door.rb +31 -146
  152. data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
  153. data/lib/hecks/facade/surface/chapter.rb +10 -54
  154. data/lib/hecks/facade/surface.rb +8 -23
  155. data/lib/hecks/facade.rb +10 -25
  156. data/lib/hecks/forms/app.rb +15 -70
  157. data/lib/hecks/forms/command_form_renderer.rb +10 -29
  158. data/lib/hecks/forms/field_renderer.rb +17 -156
  159. data/lib/hecks/forms/field_shape.rb +30 -222
  160. data/lib/hecks/forms/html.rb +12 -47
  161. data/lib/hecks/forms/index_renderer.rb +1 -4
  162. data/lib/hecks/forms/page.rb +3 -9
  163. data/lib/hecks/forms/params.rb +14 -60
  164. data/lib/hecks/forms/port_argument.rb +2 -19
  165. data/lib/hecks/forms/query_form_renderer.rb +4 -79
  166. data/lib/hecks/forms/record_renderer.rb +8 -75
  167. data/lib/hecks/forms/record_table.rb +7 -50
  168. data/lib/hecks/forms/reference_options.rb +3 -30
  169. data/lib/hecks/forms/value_object_shape.rb +8 -35
  170. data/lib/hecks/forms.rb +5 -33
  171. data/lib/hecks/fqn.rb +5 -12
  172. data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
  173. data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
  174. data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
  175. data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
  176. data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
  177. data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
  178. data/lib/hecks/framework.rb +11 -80
  179. data/lib/hecks/freezer.rb +5 -39
  180. data/lib/hecks/grammar/expression.bluebook +15 -40
  181. data/lib/hecks/grammar/translation.bluebook +3 -6
  182. data/lib/hecks/grammar.rb +16 -41
  183. data/lib/hecks/ir.rb +14 -83
  184. data/lib/hecks/language/adapter.bluebook +2 -7
  185. data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
  186. data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
  187. data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
  188. data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
  189. data/lib/hecks/language/bluebook/command.bluebook +27 -144
  190. data/lib/hecks/language/bluebook/entity.bluebook +24 -97
  191. data/lib/hecks/language/bluebook/policy.bluebook +16 -67
  192. data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
  193. data/lib/hecks/language/bluebook/projection.bluebook +126 -60
  194. data/lib/hecks/language/bluebook/query.bluebook +12 -43
  195. data/lib/hecks/language/bluebook/shape.bluebook +23 -73
  196. data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
  197. data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
  198. data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
  199. data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
  200. data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
  201. data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
  202. data/lib/hecks/language/oidc.json +35 -0
  203. data/lib/hecks/language/port.bluebook +4 -17
  204. data/lib/hecks/language/translation/translation.bluebook +3 -9
  205. data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
  206. data/lib/hecks/language/world/wiring.bluebook +1 -3
  207. data/lib/hecks/language/world/world.bluebook +5 -7
  208. data/lib/hecks/literal.rb +8 -50
  209. data/lib/hecks/mcp_door_scope.rb +95 -0
  210. data/lib/hecks/mcp_stdio_guard.rb +4 -41
  211. data/lib/hecks/naming.rb +29 -137
  212. data/lib/hecks/ports/access_control.rb +7 -23
  213. data/lib/hecks/ports/agent/answers.rb +5 -23
  214. data/lib/hecks/ports/agent.rb +47 -172
  215. data/lib/hecks/ports/authentication.rb +12 -39
  216. data/lib/hecks/ports/authorization.rb +16 -43
  217. data/lib/hecks/ports/clock.rb +5 -45
  218. data/lib/hecks/ports/extraction.rb +7 -12
  219. data/lib/hecks/ports/identity_assignment.rb +8 -29
  220. data/lib/hecks/ports/identity_generation.rb +6 -29
  221. data/lib/hecks/ports/identity_resolution.rb +2 -10
  222. data/lib/hecks/ports/key_vault.rb +9 -45
  223. data/lib/hecks/ports/persistence/append_only.rb +62 -65
  224. data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
  225. data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
  226. data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
  227. data/lib/hecks/ports/persistence/plugin.rb +13 -42
  228. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
  229. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
  230. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
  231. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
  232. data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
  233. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
  241. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
  242. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
  243. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
  244. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
  245. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
  246. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
  247. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
  248. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
  249. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
  250. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
  251. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
  252. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
  253. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
  254. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
  255. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
  256. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
  257. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
  258. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
  259. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
  260. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
  261. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
  262. data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
  263. data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
  264. data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
  265. data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
  266. data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
  267. data/lib/hecks/ports/persistence/state_codec.rb +23 -103
  268. data/lib/hecks/ports/persistence.rb +7 -14
  269. data/lib/hecks/ports/projection.rb +42 -84
  270. data/lib/hecks/ports/query/in_memory.rb +10 -58
  271. data/lib/hecks/ports/query/ordering.rb +11 -32
  272. data/lib/hecks/ports/query.rb +14 -37
  273. data/lib/hecks/ports.rb +2 -8
  274. data/lib/hecks/projections/bootstrap_table.rb +11 -43
  275. data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
  276. data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
  277. data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
  278. data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
  279. data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
  280. data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
  281. data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
  282. data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
  283. data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
  284. data/lib/hecks/projections/deploy/fargate.rb +35 -202
  285. data/lib/hecks/projections/deploy/lambda.rb +151 -679
  286. data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
  287. data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
  288. data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
  289. data/lib/hecks/projections/deploy/preview/script.rb +2 -14
  290. data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
  291. data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
  292. data/lib/hecks/projections/deploy/preview/template.rb +2 -58
  293. data/lib/hecks/projections/deploy/preview.rb +2 -67
  294. data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
  295. data/lib/hecks/projections/deploy/scripts.rb +4 -57
  296. data/lib/hecks/projections/deploy/shared.rb +47 -146
  297. data/lib/hecks/projections/deploy/smoke.rb +4 -61
  298. data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
  299. data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
  300. data/lib/hecks/projections/deploy/template_diff.rb +5 -57
  301. data/lib/hecks/projections/diagrams.rb +20 -582
  302. data/lib/hecks/projections/glossary/html.rb +14 -130
  303. data/lib/hecks/projections/glossary/markdown.rb +8 -69
  304. data/lib/hecks/projections/glossary/mermaid.rb +9 -66
  305. data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
  306. data/lib/hecks/projections/glossary/sentences.rb +14 -159
  307. data/lib/hecks/projections/glossary.rb +30 -222
  308. data/lib/hecks/projections/ir.rb +3 -10
  309. data/lib/hecks/projections/model/deviations.rb +15 -42
  310. data/lib/hecks/projections/model.rb +12 -51
  311. data/lib/hecks/projections/oidc.rb +12 -56
  312. data/lib/hecks/projections/parser_table.rb +9 -28
  313. data/lib/hecks/projections/reference.rb +9 -16
  314. data/lib/hecks/projections/rust_vocabulary.rb +12 -250
  315. data/lib/hecks/projections/shape.rb +3 -29
  316. data/lib/hecks/projections/statements.rb +7 -86
  317. data/lib/hecks/projections/vocabulary.rb +6 -22
  318. data/lib/hecks/projections.rb +2 -16
  319. data/lib/hecks/projector/cli_projector.rb +60 -375
  320. data/lib/hecks/projector/docs_projector.rb +10 -201
  321. data/lib/hecks/projector/exporter.rb +46 -138
  322. data/lib/hecks/projector/ir_projector.rb +2 -9
  323. data/lib/hecks/projector/narrate_projector.rb +15 -189
  324. data/lib/hecks/projector/target.rb +13 -76
  325. data/lib/hecks/projector.rb +30 -121
  326. data/lib/hecks/query_specification/common/comparators.rb +5 -26
  327. data/lib/hecks/query_specification/common/comparison.rb +35 -143
  328. data/lib/hecks/query_specification/common/dsl.rb +8 -24
  329. data/lib/hecks/query_specification/common/null_policy.rb +20 -70
  330. data/lib/hecks/query_specification/common/options.rb +2 -6
  331. data/lib/hecks/query_specification/common/where_clause.rb +2 -10
  332. data/lib/hecks/query_specification/field_path.rb +37 -77
  333. data/lib/hecks/query_specification/hop_path.rb +12 -76
  334. data/lib/hecks/release/gem_pin.rb +2 -26
  335. data/lib/hecks/release/runner/ci_publisher.rb +93 -0
  336. data/lib/hecks/release/runner/commands.rb +66 -0
  337. data/lib/hecks/release/runner/console.rb +52 -0
  338. data/lib/hecks/release/runner/gem_publisher.rb +43 -0
  339. data/lib/hecks/release/runner/git.rb +48 -0
  340. data/lib/hecks/release/runner/npm_publisher.rb +75 -0
  341. data/lib/hecks/release/runner/preflight.rb +104 -0
  342. data/lib/hecks/release/runner/published.rb +55 -0
  343. data/lib/hecks/release/runner/tagger.rb +80 -0
  344. data/lib/hecks/release/runner.rb +215 -0
  345. data/lib/hecks/rendering.rb +4 -26
  346. data/lib/hecks/router/namespace_installer.rb +12 -36
  347. data/lib/hecks/router.rb +4 -8
  348. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  349. data/lib/hecks/runtime/boot_gates.rb +3 -18
  350. data/lib/hecks/runtime/caller.rb +19 -59
  351. data/lib/hecks/runtime/capability_graph.rb +5 -21
  352. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  353. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
  354. data/lib/hecks/runtime/command_interpreter.rb +125 -307
  355. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  356. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  357. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  358. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  359. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  360. data/lib/hecks/runtime/dependency_planning.rb +30 -102
  361. data/lib/hecks/runtime/dispatcher.rb +82 -241
  362. data/lib/hecks/runtime/entity_element.rb +40 -462
  363. data/lib/hecks/runtime/entity_interpreter.rb +65 -220
  364. data/lib/hecks/runtime/errors.rb +32 -115
  365. data/lib/hecks/runtime/event.rb +3 -25
  366. data/lib/hecks/runtime/identity.rb +18 -154
  367. data/lib/hecks/runtime/instance.rb +18 -150
  368. data/lib/hecks/runtime/interpreting.rb +11 -70
  369. data/lib/hecks/runtime/invocation.rb +28 -164
  370. data/lib/hecks/runtime/loader.rb +48 -186
  371. data/lib/hecks/runtime/outbox.rb +38 -261
  372. data/lib/hecks/runtime/policy_interpreter.rb +38 -200
  373. data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
  374. data/lib/hecks/runtime/query_interpreter.rb +45 -187
  375. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  376. data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
  377. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  378. data/lib/hecks/runtime/reference_hop.rb +8 -81
  379. data/lib/hecks/runtime/refusal_wording.rb +8 -89
  380. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  381. data/lib/hecks/runtime/registry/verification.rb +52 -225
  382. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  383. data/lib/hecks/runtime/registry.rb +103 -244
  384. data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
  385. data/lib/hecks/runtime/routing.rb +4 -15
  386. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  387. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  388. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  389. data/lib/hecks/runtime/tenant_check.rb +6 -68
  390. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  391. data/lib/hecks/runtime/value/admission.rb +16 -67
  392. data/lib/hecks/runtime/value/coercion.rb +155 -641
  393. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  394. data/lib/hecks/runtime/value.rb +12 -84
  395. data/lib/hecks/runtime.rb +17 -65
  396. data/lib/hecks/storehouse.rb +146 -567
  397. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
  398. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  399. data/lib/hecks/vendoring/git_environment.rb +2 -8
  400. data/lib/hecks/vendoring/git_source.rb +4 -10
  401. data/lib/hecks/vendoring.rb +7 -46
  402. data/lib/hecks/version.rb +3 -14
  403. data/lib/hecks/vocabulary.rb +5 -0
  404. data/lib/hecks.rb +32 -82
  405. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  406. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  407. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  408. metadata +30 -59
  409. data/lib/hecks/bench/cli.rb +0 -74
  410. data/lib/hecks/bench/environment.rb +0 -100
  411. data/lib/hecks/bench/postgres_probe.rb +0 -41
  412. data/lib/hecks/bench/report.rb +0 -116
  413. data/lib/hecks/bench/ruby_runner.rb +0 -151
  414. data/lib/hecks/bench/run.rb +0 -55
  415. data/lib/hecks/bench/rust_runner.rb +0 -165
  416. data/lib/hecks/bench/stats.rb +0 -75
  417. data/lib/hecks/bench/suite.rb +0 -172
  418. data/lib/hecks/bench/workload.rb +0 -137
  419. data/lib/hecks/bench.rb +0 -28
  420. data/lib/hecks/codemod.rb +0 -443
  421. data/lib/hecks/corpus.rb +0 -479
  422. data/lib/hecks/doc/reference.rb +0 -585
  423. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
  424. data/lib/hecks/fuzzing/combination_miner.rb +0 -178
  425. data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
  426. data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
  427. data/lib/hecks/fuzzing/differential.rb +0 -192
  428. data/lib/hecks/fuzzing/domain_generator.rb +0 -871
  429. data/lib/hecks/fuzzing/era_boundary.rb +0 -154
  430. data/lib/hecks/fuzzing/form_census.rb +0 -285
  431. data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
  432. data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
  433. data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
  434. data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
  435. data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
  436. data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
  437. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
  438. data/lib/hecks/fuzzing/properties/guards.rb +0 -398
  439. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
  440. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
  441. data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
  442. data/lib/hecks/fuzzing/properties/querying.rb +0 -260
  443. data/lib/hecks/fuzzing/properties.rb +0 -267
  444. data/lib/hecks/fuzzing/qa_settings.rb +0 -164
  445. data/lib/hecks/fuzzing/replay.rb +0 -930
  446. data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
  447. data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
  448. data/lib/hecks/fuzzing/self_consistency.rb +0 -825
  449. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
  450. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
  451. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
  452. data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
  453. data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
  454. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
  455. data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
  456. data/lib/hecks/fuzzing/shrinker.rb +0 -309
  457. data/lib/hecks/fuzzing/structural_skips.rb +0 -53
  458. data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
  459. data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
  460. data/lib/hecks/fuzzing/value_generator.rb +0 -340
  461. data/lib/hecks/fuzzing.rb +0 -23
  462. data/lib/hecks/grammar/evolve.rb +0 -524
  463. data/lib/hecks/query_ir.rb +0 -482
data/lib/hecks/ir.rb CHANGED
@@ -1,95 +1,36 @@
1
1
  module Hecks
2
- # What a construct emits, declared rather than written out.
3
- #
4
- # `IR` is a thing this framework produces, not a thing its model is.
5
- # The language self-hosts, and its own bluebook declares aggregates
6
- # named `Bluebook`, `Aggregate`, `Command`, `Entity`, `ValueObject`,
7
- # `Policy`, `ReadModel` — there is no `IR` aggregate anywhere in the
8
- # grammar. Where the grammar's own vision line does say IR it means the
9
- # emission: "the IR it stores must equal the IR the DSL builder
10
- # produces". `IR_VERSION` says the same thing structurally — a version
11
- # stamped on `to_h`'s output rather than on the object is a version of
12
- # the emission, which only makes sense if the two are different things.
13
- #
14
- # So emitting IR is a capability a construct has, and this is that
15
- # capability: `include Hecks::IR` and declare the shape once.
16
- # The model it emits from is `Hecks::Bluebook` — a chapter class
17
- # nesting everything a chapter declares. It is deliberately not named
18
- # after this, its own output.
19
- #
20
- # ## Why declared, not hand-written
21
- #
22
- # A hand-written `to_h` per construct would say the same four things in the
23
- # same order — read a field, recurse into a child, recurse into a list, or
24
- # compute something — leaving a construct's shape knowable only by reading a
25
- # method body. Declared, it is data: `ir_spec` can be walked by anything
26
- # that wants to know what a construct carries, which is the whole point of
27
- # hanging emission off the model rather than burying it.
28
- #
29
- # ## Usage
30
- #
31
- # include Hecks::IR # an instance-shaped construct
2
+ # Declares what a construct emits as IR, so its shape is data rather than a hand-written `to_h`.
32
3
  #
33
4
  # emits_ir(
34
- # name: :name, # send it
35
- # identified_by: :identity_paths, # ...under a different key
36
- # list: :list?, # ...predicates are fine
37
- # attributes: many(:attributes), # map(&:to_h)
38
- # lifecycle: one(:lifecycle), # &.to_h, nil-safe
39
- # canonical_form: -> { CanonicalForm.table } # anything else
5
+ # name: :name, # send it
6
+ # attributes: many(:attributes), # map(&:to_h)
7
+ # lifecycle: one(:lifecycle), # &.to_h, nil-safe
8
+ # canonical_form: -> { CanonicalForm.table } # instance_exec'd
40
9
  # )
41
10
  #
42
- # Key order is the declaration order, and that is load-bearing rather
43
- # than cosmetic: `spec/golden/ir/*.json` pins the emitted form exactly,
44
- # so a reordered declaration is a changed artifact and the golden specs
45
- # will say so.
11
+ # Key order is declaration order; spec/golden/ir/*.json pins the emitted form.
46
12
  module IR
47
- # The two shapes a construct comes in, and why this module has two
48
- # doors instead of hiding the difference.
49
- #
50
- # `Bluebook`/`Aggregate`/`Policy`/`ReadModel` are ordinary objects —
51
- # metadata records, one instance per declaration. `Command`/`Entity`/
52
- # `ValueObject` are anonymous classes (`Class.new(self)`, see
53
- # `Command.declare`), because those three are referenced as types in
54
- # a bluebook (`attribute :price, Money`) and a type has to be a real
55
- # Ruby constant to be named.
56
- #
57
- # That split is real and not worth papering over, so:
58
- #
59
- # include Hecks::IR # instance-shaped — to_h is an instance method
60
- # extend Hecks::IR # class-shaped — to_h is a class method
61
- #
62
- # Both get the same `emits_ir` and the same emission rules.
13
+ # Instance-shaped constructs (`Aggregate`, `Policy`) `include Hecks::IR`; class-shaped ones
14
+ # (`Command`, `Entity`, `ValueObject`, which are named as types) `extend` it.
63
15
  #
64
16
  # Wires an instance-shaped construct's declaration and emission sides in.
65
- #
66
- # @param base [Class, Module] the includer
67
- # @return [void]
68
17
  def self.included(base)
69
18
  base.extend(Declares)
70
19
  base.include(Emits)
71
20
  end
72
21
 
73
22
  # Wires a class-shaped construct's declaration and emission sides in.
74
- #
75
- # @param base [Class, Module] the extender
76
- # @return [void]
77
23
  def self.extended(base)
78
24
  base.extend(Declares)
79
25
  base.extend(Emits)
80
26
  end
81
27
 
82
- # A field that holds a list of constructs — each one emits itself.
28
+ # A field that holds a list of constructs, each emitting itself.
83
29
  Many = Struct.new(:source)
84
- # A field that holds one construct, or nothing. `&.to_h`, never a
85
- # crash on an undeclared lifecycle.
30
+ # A field that holds one construct, or nil.
86
31
  One = Struct.new(:source)
87
32
 
88
- # The declaration side: `emits_ir(**spec)` records a construct's field ->
89
- # rule map, `many`/`one` wrap a source name so a field can recurse into a
90
- # list or a single nested construct, and `ir_spec` reads the declaration
91
- # back — walking the superclass chain so an anonymous `Class.new(base)`
92
- # inherits its base's shape instead of redeclaring it.
33
+ # The declaration side: `emits_ir`, `many`, `one`, and `ir_spec` to read the shape back.
93
34
  module Declares
94
35
  # Records this construct's field -> emission-rule map.
95
36
  #
@@ -113,14 +54,9 @@ module Hecks
113
54
  # @return [One] the wrapped source, for `emits_ir`
114
55
  def one(source) = One.new(source)
115
56
 
116
- # Walks the superclass chain so a `Class.new(ValueObject)` — which
117
- # is what every declared value object actually is — inherits the
118
- # shape its base declared, rather than each anonymous subclass
119
- # having to redeclare it.
57
+ # Walks the superclass chain so a `Class.new(ValueObject)` inherits its base's shape.
120
58
  #
121
- # @return [Hash{Symbol => Symbol, Many, One, Proc}, nil] the field -> rule
122
- # map declared by `emits_ir`, inherited from the nearest superclass that
123
- # declared one; nil if nothing in the chain ever declared a shape
59
+ # @return [Hash{Symbol => Symbol, Many, One, Proc}, nil] the declared field -> rule map
124
60
  def ir_spec
125
61
  return @ir_spec if defined?(@ir_spec) && @ir_spec
126
62
 
@@ -128,10 +64,7 @@ module Hecks
128
64
  end
129
65
  end
130
66
 
131
- # The emission side: `to_h` reads the declaring construct's `ir_spec` and
132
- # applies each field's rule (`Many#to_h`, `One&.to_h`, a plain Symbol
133
- # send, or an instance-`exec`'d Proc) in declaration order to build the
134
- # actual Hash.
67
+ # Emits the Hash a construct's `emits_ir` declaration describes, in declaration order.
135
68
  module Emits
136
69
  def to_h
137
70
  spec = ir_spec_for(self)
@@ -142,8 +75,6 @@ module Hecks
142
75
 
143
76
  private
144
77
 
145
- # An instance reads its class's declaration; a class-shaped
146
- # construct is the declaration holder.
147
78
  def ir_spec_for(construct)
148
79
  return construct.ir_spec if construct.respond_to?(:ir_spec)
149
80
 
@@ -31,10 +31,7 @@ Hecks.bluebook "Adapter" do
31
31
  goal "Register a real implementation of one resource port"
32
32
 
33
33
  attribute :name, AdapterName
34
- # OPTIONAL — real, pre-existing AdapterBuilder behavior (spec/
35
- # dsl_spec.rb's own "field names a config value..." and "secret
36
- # names one too..." each build an adapter with only `field`/
37
- # `secret`, never calling `port` at all).
34
+ # Optional: an adapter may declare only fields or secrets and never name a port.
38
35
  attribute :port, AdapterPortName, optional: true
39
36
 
40
37
  sets :name
@@ -67,9 +64,7 @@ Hecks.bluebook "Adapter" do
67
64
  emits "AdapterSecretAdded"
68
65
  end
69
66
 
70
- # HOW ADAPTER IS SPELLED. These rows live with the concept
71
- # they describe; SyntaxBoot discovers every aggregate-local seed table.
72
- # Contexts represented here: File, Adapter.
67
+ # Grammar rows for the `adapter` keyword; SyntaxBoot discovers aggregate-local seed tables.
73
68
  value_object "KeywordSeed" do
74
69
  attribute :word, String
75
70
  attribute :context, String, admits: "Syntax::Context"
@@ -4,47 +4,27 @@ Hecks.bluebook "Bluebook" do
4
4
 
5
5
  reference_to Bluebook
6
6
 
7
- # THE CHAPTER IT IS IN, AND ITS NAME. `Order` names nothing on its own — two
8
- # chapters may both declare one — so the chapter is part of the identity, not
9
- # context around it. This is the derivation `MetaValidator::Judge#identify`
10
- # spelled by hand as "#{parent_id}::#{name}" for as long as the language could
11
- # not say it.
7
+ # The chapter is part of the identity: two chapters may each declare an `Order`.
12
8
  identified_by :bluebook, :name
13
9
 
14
- # SPELLED AS THE IR SPELLS THEM — see the note on Command's fields.
15
10
  attribute :name, AggregateName
16
11
  attribute :description, Description
17
12
  attribute :provenance, LiteralText
18
- # SEVERAL PATHS, because the identity is their JOIN. One is the ordinary case ;
19
- # more than one is what anything named BENEATH another thing needs, and the
20
- # language's own chapters are all of that kind — a command is not named by
21
- # `Declare`, which every aggregate here spells, but by the aggregate it belongs
22
- # to AND that name. Held as a list for the same reason attributes are : the
23
- # order is a fact about the source, and the join reads in it.
13
+ # Several paths, because the identity is their join in declared order: a command is named
14
+ # by its aggregate and its own name.
24
15
  attribute :identified_by, list_of(IdentityPath)
25
16
  attribute :attributes, list_of(Field)
26
17
  attribute :value_objects, list_of(ValueName)
27
18
  attribute :state_field, IdentityField, optional: true
28
19
  attribute :state_start, IdentityField, optional: true
29
20
  attribute :transitions, list_of(Transition)
30
- # THE AGGREGATE BOUNDARY (S10, ADR 0025 — "Rules") — checked after
31
- # every command, before save, the SAME Rule shape Command's own
32
- # givens/ensures already carry (description+canonical), declared
33
- # again here rather than shared: a closed set/value object is
34
- # aggregate-scoped in this self-hosting domain, the same reason
35
- # CommandText and LiteralText stay two separate, identically-
36
- # shaped value objects rather than one reused across chapters.
21
+ # Checked after every command, before save (ADR 0025). The same Rule shape as Command's
22
+ # givens, declared again because a closed set or value object is aggregate-scoped here.
37
23
  attribute :invariants, list_of(Rule)
38
- # A PRECONDITION SHARED ACROSS COMMANDS, DECLARED ONCE (S10, ADR
39
- # 0025) — the SAME Rule shape, the aggregate's own named `given`s
40
- # that a referencing command's own (already-resolved) `given`
41
- # entry came from.
24
+ # A precondition shared across commands, declared once: the aggregate's named `given`s.
42
25
  attribute :preconditions, list_of(Rule)
43
- # A FIELD READ THROUGH A REFERENCE, HELD LOCALLY (S12, ADR 0025 —
44
- # "Consistency across aggregate boundaries") — the local half of
45
- # `projects :name, from: :"reference.remote_field"`. Deliberately
46
- # NOT folded into `attributes` — see the comment on
47
- # `Aggregate#emits_ir`'s own `projected_fields:` entry for why.
26
+ # A field read through a reference and held locally (`projects :name, from: :"ref.field"`).
27
+ # Kept out of `attributes`; see `projected_fields:` in `Aggregate#emits_ir` (ADR 0025).
48
28
  attribute :projected_fields, list_of(ProjectedField)
49
29
 
50
30
  value_object "AggregateName" do
@@ -61,14 +41,8 @@ Hecks.bluebook "Bluebook" do
61
41
  attribute :value, String
62
42
  end
63
43
 
64
- # ONE PART OF AN IDENTITY — a path down to the SCALAR that carries it, like
65
- # "number.value". A part on its own is not an identity ; the identity is every
66
- # part joined, in the order they were declared.
67
- #
68
- # Its field is `value`, like every other one-field value object in this
69
- # language, because that is the name the judge wraps a cell under. Spelling it
70
- # `path` made `path.path` read nothing, and a given that reads nothing does not
71
- # fail — it refuses everything, which is a far quieter way to be wrong.
44
+ # One part of an identity: a path to the scalar that carries it, like "number.value".
45
+ # Its field is `value`, the name the judge wraps a cell under; any other name reads nothing.
72
46
  value_object "IdentityPath" do
73
47
  attribute :value, String
74
48
  end
@@ -79,22 +53,13 @@ Hecks.bluebook "Bluebook" do
79
53
  attribute :list, String
80
54
  attribute :optional, String, optional: true
81
55
  attribute :pattern, String, optional: true
82
- # Held as a LITERAL, written so its type survives — 0.0 rather than "0.0".
83
- # Without this an aggregate attribute's default was simply dropped, and the
84
- # reconstruction hardcoded nil, which happened to match every corpus member
85
- # and would have lied about the first one that declared a default.
86
- # optional: a declaration with no default has none (C3.7 — a value object's fields arrive or it refuses)
56
+ # A literal written so its type survives: 0.0 rather than "0.0".
57
+ # optional: a declaration with no default has none.
87
58
  attribute :default, String, optional: true
88
- # THE CLOSED SET THIS VALUE MUST BELONG TO, named where it was already
89
- # declared — `Vocabulary::QueryComparator`. Qualified by the aggregate that
90
- # holds it, because a closed set is a value object INSIDE an aggregate and
91
- # the aggregate is the only thing a reference can reach ; `one_of` is the
92
- # other word and it can only ever SYNTHESISE a new set, never name one
93
- # twice. Absent for almost every attribute, so it is optional.
59
+ # The closed set this value must belong to, qualified by its aggregate
60
+ # (`Vocabulary::QueryComparator`); `one_of` can only synthesise a new set, never name one.
94
61
  attribute :admits, String, optional: true
95
- # `reference_to`, `belongs_to`, `has_one`, or `has_many`; absent on
96
- # ordinary value/entity fields. This keeps relationship language through
97
- # the self-hosted round trip instead of collapsing it to a reference.
62
+ # `reference_to`, `belongs_to`, `has_one` or `has_many`; absent on ordinary fields.
98
63
  attribute :relationship, String, optional: true
99
64
  end
100
65
 
@@ -109,19 +74,14 @@ Hecks.bluebook "Bluebook" do
109
74
  attribute :to_state, String
110
75
  end
111
76
 
112
- # THE SAME SHAPE Command's own "Rule" value object carries — see
113
- # behavior.bluebook — declared again here rather than shared, per
114
- # that value object's own comment.
77
+ # The same shape as Command's "Rule" (behavior.bluebook), declared again rather than shared.
115
78
  value_object "Rule" do
116
79
  attribute :description, String
117
80
  attribute :canonical, String
118
81
  end
119
82
 
120
- # S12, ADR 0025 — `name` is this aggregate's own field being
121
- # declared; `reference` names the local `reference_to` attribute to
122
- # read through; `remote_field` names the scalar on the target. All
123
- # three are plain identifiers, the same shape `Field#name`/`#type`
124
- # already are.
83
+ # `reference` names the local `reference_to` attribute to read through; `remote_field`
84
+ # the scalar on its target.
125
85
  value_object "ProjectedField" do
126
86
  attribute :name, String
127
87
  attribute :reference, String
@@ -135,10 +95,7 @@ Hecks.bluebook "Bluebook" do
135
95
  reference_to Bluebook
136
96
  attribute :name, AggregateName
137
97
  attribute :description, Description, optional: true
138
- # See Command.Declare's own `provenance` — identical shape, one
139
- # level up. LiteralText, not a dedicated value object: the field
140
- # rides the same self-describing `inspect` encoding `default:`
141
- # already uses, so it needs no invariant of its own.
98
+ # LiteralText: rides the same `inspect` encoding as `default:`, so it needs no invariant.
142
99
  attribute :provenance, LiteralText, optional: true
143
100
 
144
101
  attribute :position, Position, optional: true
@@ -151,60 +108,30 @@ Hecks.bluebook "Bluebook" do
151
108
  emits RootDeclared
152
109
  end
153
110
 
154
- # ONE PART OF THE IDENTITY, attached the way one attribute is. It was an
155
- # argument on Declare while an identity was a single field ; a list cannot be
156
- # carried by one argument, and every other list in this language is filled by
157
- # a verb of its own, so this is the shape that was already here.
111
+ # One part of the identity, attached the way one attribute is.
158
112
  command "Identify" do
159
113
  role "Language"
160
114
  goal "Attach one part of the aggregate's identity"
161
115
 
162
116
  attribute :path, IdentityPath
163
117
 
164
- # AN IDENTITY PART NAMES SOMETHING. This rule used to sit on Seal reading
165
- # `empty? || == "id" || includes(".")` — two escapes and a check. The escapes
166
- # were the whole of it : `empty?` let an aggregate say nothing and be given a
167
- # minted `id`, and `== "id"` let it name that slot outright. Both are gone,
168
- # so what is left is the rule itself, and it now runs on every part rather
169
- # than on whichever one a single field happened to hold.
170
- #
171
- # THREE WAYS TO REACH A SCALAR (ADR 0025, "Identity"), and this given no
172
- # longer distinguishes them — it used to accept only a dotted path
173
- # (`number.value`, a value object's own field) or an `_id`-suffixed
174
- # reference, and REFUSED a bare scalar field (`sku`), which is legal
175
- # too : a plain primitive attribute IS already a scalar, nothing to
176
- # open. That distinction belongs to the BUILDER, which resolves each
177
- # spelling before an identity part ever reaches here
178
- # (`AttributeCollector#resolve_identity_field!` — the single place
179
- # that decides dotted-unwrap vs. reference vs. bare-scalar, and the
180
- # only place that can, since it alone holds the attribute's declared
181
- # type). What is left for THIS rule to say, once the builder has
182
- # already resolved a real shape, is only that a part was actually
183
- # given a name at all.
118
+ # The builder resolves each spelling (dotted path, reference, bare scalar) before a part
119
+ # arrives (`AttributeCollector#resolve_identity_field!`); this rule only asks it is named.
184
120
  given("an identity part names something") { !path.value.to_s.empty? }
185
121
 
186
122
  sets :identified_by, append: { value: :path }
187
123
  emits RootIdentified
188
124
  end
189
125
 
190
- # The way back, one level down: the aggregates DECLARED IN a chapter, found by
191
- # the chapter that declared them. The parent reference IS the query.
192
- #
193
- # `bluebook_id` is an IdentityField, not an AggregateName — it holds the id of
194
- # the chapter above, and calling that a name for aggregates was sloppiness that
195
- # would read as a lie the first time somebody looked.
196
- # WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
197
- # SOURCE — the IR is a contract read straight from this file,
198
- # field for field AND INDEX FOR INDEX. So the language HOLDS it, instead of
199
- # inheriting it from whatever order a store happens to iterate: an ask that
200
- # does not say how it is ordered is answered in identity order, which is
201
- # right for every other ask and fatal for the one that is the SOURCE.
126
+ # Declaration order is a fact about the source: the IR is read index for index, so the language
127
+ # holds it rather than inheriting a store's iteration order.
202
128
  value_object "Position" do
203
129
  attribute :value, Integer
204
130
  end
205
131
 
206
132
  attribute :position, Position
207
133
 
134
+ # The aggregates declared in a chapter; the parent reference is the query.
208
135
  query "DeclaredIn" do
209
136
  attribute :bluebook, IdentityField
210
137
  where(bluebook: :bluebook)
@@ -215,26 +142,17 @@ Hecks.bluebook "Bluebook" do
215
142
  role "Language"
216
143
  goal "Attach one attribute to the aggregate"
217
144
 
218
- # The TYPE is a reference to the value object it names. An attribute
219
- # naming an undeclared value object then fails REFERENCE RESOLUTION —
220
- # "no Shape with id …" — with no predicate at all.
221
- #
222
- # This is the rule "attributes must use value-object types", which could
223
- # not be a `given` : it needs, for each element of a list, a check against
224
- # another list, and the sublanguage has no quantifier and cannot see
225
- # inside a list element. As a reference it stops being a predicate and
226
- # becomes a consequence of the model.
145
+ # The type is a reference to the value object it names, so an undeclared type fails reference
146
+ # resolution. A `given` cannot state this: the sublanguage has no quantifier over a list.
227
147
  reference_to ValueObject, as: :type
228
148
  attribute :name, FieldName
229
149
  attribute :list, ListFlag
230
150
  attribute :optional, ListFlag, optional: true
231
- # A PATTERN IS A REGEX, not a flag — see the note on ListFlag below.
151
+ # A pattern is a regex, not a flag (see ListFlag).
232
152
  attribute :pattern, LiteralText, optional: true
233
153
  attribute :default, LiteralText, optional: true
234
- # FREE TEXT, not a reference. A closed set is a value object INSIDE an
235
- # aggregate, and `reference_to` reaches heads only — so the qualified name
236
- # is carried as text and checked where it is READ, by the reader, which
237
- # already raises for the other things the language cannot say about itself.
154
+ # Free text, not a reference: `reference_to` reaches heads only, so the qualified name
155
+ # is carried as text and checked by the reader.
238
156
  attribute :admits, LiteralText, optional: true
239
157
  attribute :relationship, LiteralText, optional: true
240
158
 
@@ -243,34 +161,19 @@ Hecks.bluebook "Bluebook" do
243
161
  emits AttributeAttached
244
162
  end
245
163
 
246
- # An attribute that points at ANOTHER aggregate's head.
247
- #
248
- # `Attribute` types its type as `reference_to ValueObject`, which is what makes
249
- # "attributes use value-object types" a consequence of the model rather than a
250
- # predicate. A cross-aggregate reference cannot go through it: its type is
251
- # `Reference<Customer>`, which is not a value object and never will be. So the
252
- # judge SKIPPED every one of them, and the meta-domain did not hold
253
- # Account#customer_id at all — the way back was lossy for exactly one
254
- # construct, and the comment excusing it said "the language does not model
255
- # reference-typed attributes yet".
164
+ # An attribute that points at another aggregate's head. Its type is `Reference<Customer>`,
165
+ # which is not a value object, so it cannot go through `Attribute`.
256
166
  command "Reference" do
257
167
  role "Language"
258
168
  goal "Attach an attribute that points at another aggregate's head"
259
169
 
260
- # POINTS AT a declared head, and that is the whole rule.
261
- #
262
- # This carried `attribute :type, ReferenceType` — a STRING — with an invariant
263
- # apologising for itself, because the shape that actually tells a reference
264
- # from a value object (`Reference<Something>`) is unsayable in the predicate
265
- # sublanguage. That was never a sublanguage gap; a string was simply the wrong
266
- # model. As a reference it stops being a predicate and becomes a consequence
267
- # of the model, exactly as Attribute's type does — and it is STRONGER than the
268
- # prefix match, which only ever checked that the text looked right.
170
+ # Points at a declared head. As a reference rather than a string predicate on
171
+ # `Reference<...>`, it is a consequence of the model and stricter than a prefix match.
269
172
  reference_to Aggregate, as: :points_at
270
173
  attribute :name, FieldName
271
174
  attribute :list, ListFlag
272
175
  attribute :optional, ListFlag, optional: true
273
- # A PATTERN IS A REGEX, not a flag — see the note on ListFlag below.
176
+ # A pattern is a regex, not a flag (see ListFlag).
274
177
  attribute :pattern, LiteralText, optional: true
275
178
  attribute :default, LiteralText, optional: true
276
179
  attribute :admits, LiteralText, optional: true
@@ -281,14 +184,8 @@ Hecks.bluebook "Bluebook" do
281
184
  emits ReferenceAttached
282
185
  end
283
186
 
284
- # An attribute whose type names a PIECE this aggregate holds.
285
- #
286
- # `Account#ledger` is a list of LedgerEntry — neither a value object nor another
287
- # aggregate's head — so it fitted no verb and the walk skipped it, the last
288
- # construct the way back could not carry. Same trick as Reference: point at the
289
- # entity's own declaration, and "an aggregate holds a piece it declared" costs
290
- # no predicate at all. Entities are declared before attributes are offered, so
291
- # the reference resolves.
187
+ # An attribute whose type is an entity this aggregate holds, e.g. `Account#ledger`.
188
+ # Entities are declared before attributes are offered, so the reference resolves.
292
189
  command "Holds" do
293
190
  role "Language"
294
191
  goal "Attach an attribute whose type is a piece of this aggregate"
@@ -297,7 +194,7 @@ Hecks.bluebook "Bluebook" do
297
194
  attribute :name, FieldName
298
195
  attribute :list, ListFlag
299
196
  attribute :optional, ListFlag, optional: true
300
- # A PATTERN IS A REGEX, not a flag — see the note on ListFlag below.
197
+ # A pattern is a regex, not a flag (see ListFlag).
301
198
  attribute :pattern, LiteralText, optional: true
302
199
  attribute :default, LiteralText, optional: true
303
200
  attribute :admits, LiteralText, optional: true
@@ -308,14 +205,8 @@ Hecks.bluebook "Bluebook" do
308
205
  emits PieceHeld
309
206
  end
310
207
 
311
- # THE ONLY RULE THAT CAN REFUSE AN UNNAMED ATTRIBUTE, and it lives here.
312
- #
313
- # Attribute, Reference and Holds each carried `given("… is named")` beside
314
- # this, and not one of them could ever fire: an EMPTY name builds the value
315
- # object and this invariant refuses first, while an ABSENT name builds no
316
- # value object and the given did not refuse at all — probed, not reasoned.
317
- # Three rules that read as rules and were decoration. A predicate cannot
318
- # guard what a type already guards.
208
+ # The only rule that refuses an unnamed attribute. A `given` beside it could never fire:
209
+ # an empty name is refused here first, and an absent name builds no value object.
319
210
  value_object "FieldName" do
320
211
  attribute :value, String
321
212
  invariant("an attribute is named") { !value.to_s.empty? }
@@ -326,24 +217,13 @@ Hecks.bluebook "Bluebook" do
326
217
  invariant("a type is named") { !value.to_s.empty? }
327
218
  end
328
219
 
329
- # A literal written the way it can be read back — see Readings#encode_literal.
220
+ # A literal written the way it can be read back (Readings#encode_literal).
330
221
  value_object "LiteralText" do
331
222
  attribute :value, String
332
223
  end
333
224
 
334
- # TRUE OR FALSE, AND NOTHING ELSE. `list` and `optional` are the two fields
335
- # this is about — they are the answers to a yes/no question, written as text
336
- # because that is what the wire carries.
337
- #
338
- # `pattern` was typed with it too, which is not a loose typing but a FALSE
339
- # one: a pattern holds a regex, and this invariant admits exactly two strings
340
- # neither of which is one. It never fired only because no aggregate-level or
341
- # entity-level attribute in the corpus declares a pattern — banking's one
342
- # `pattern:` sits on a VALUE OBJECT field, which is built by
343
- # `ValueObject.Field` and so went down a different command entirely. The
344
- # first head that declared a pattern would have been refused by a rule about
345
- # lists. It is `LiteralText` now, which is what the other four element
346
- # builders already say a pattern is: free text.
225
+ # True or false as text, the wire form of `list` and `optional`.
226
+ # `pattern` is not typed with it: a pattern is a regex, so it is `LiteralText`.
347
227
  value_object "ListFlag" do
348
228
  attribute :value, String
349
229
  invariant("list is true or false") { value.to_s == "true" || value.to_s == "false" }
@@ -379,37 +259,11 @@ Hecks.bluebook "Bluebook" do
379
259
  role "Language"
380
260
  goal "Close an aggregate — the checks that need every declaration present"
381
261
 
382
- # The builders validate at `build`, once everything is collected. A given
383
- # fires at DISPATCH, when later declarations do not exist yet. So the
384
- # whole-document rules live on a command dispatched after the aggregate
385
- # is fully declared. This is the shape the tier-3 rules need ; whether
386
- # the sublanguage can express their CONTENT is the open question.
387
-
388
- # THE RULE THAT WAS HERE WAS NOT TRUE, and nothing could tell us while Seal
389
- # went undispatched. `given("an aggregate declares at least one attribute")`
390
- # was invented for this command — it is not one of the rules ported from the
391
- # builders, so no bluebook was ever written against it. The first time it
392
- # ran it refused twenty-five of them, including every aggregate whose state
393
- # is a `lifecycle` rather than an `attribute` : a state machine declares no
394
- # attribute and is perfectly well formed.
395
- #
396
- # Seal stays. It is the right SHAPE for a whole-document rule — dispatched
397
- # once every declaration is present — and it is now actually dispatched, so
398
- # the next rule put here will be seen refusing instead of sitting decorative.
399
- # The rule waiting for it is "a mutation names a field the aggregate has",
400
- # which lives in AggregateBuilder today because saying it here needs to reach
401
- # a list on another root.
402
- # AN AGGREGATE SAYS WHAT IT IS KNOWN BY. Nothing falls back to `id` any more.
403
- #
404
- # The fallback was never a default — it was a MINT. An aggregate that said
405
- # nothing got an id invented for it, so the same declaration named a
406
- # different record on the next run, and nothing outside the runtime could
407
- # name a record at all. The rule that stood here permitted it in as many
408
- # words (`empty? || == "id"`), and the comment named exactly who was
409
- # leaning on it : the language's own chapters, all fourteen of them.
262
+ # Builders validate at `build`, but a given fires at dispatch, before later declarations
263
+ # exist. Whole-document rules therefore live on a command dispatched after the aggregate.
410
264
  #
411
- # They derive now, like everything else does. What each PART must look like
412
- # is Identify's rule ; this one only asks that there be one.
265
+ # An aggregate says what it is known by; nothing falls back to a minted `id`.
266
+ # What each part must look like is Identify's rule; this one only asks that there be one.
413
267
  given("an aggregate says what it is known by") { !identified_by.empty? }
414
268
 
415
269
  emits RootSealed
@@ -426,8 +280,7 @@ Hecks.bluebook "Bluebook" do
426
280
  emits ValueDeclared
427
281
  end
428
282
 
429
- # THE AGGREGATE BOUNDARY (S10, ADR 0025 — "Rules") — the same shape
430
- # Command.Rule attaches a given with, one level up.
283
+ # The aggregate boundary (ADR 0025): the same shape `Command.Rule` attaches a given with.
431
284
  command "Invariant" do
432
285
  role "Language"
433
286
  goal "Attach one invariant to the aggregate"
@@ -443,9 +296,7 @@ Hecks.bluebook "Bluebook" do
443
296
  emits InvariantAttached
444
297
  end
445
298
 
446
- # A PRECONDITION SHARED ACROSS COMMANDS, DECLARED ONCE (S10, ADR
447
- # 0025) — the aggregate's own named `given`, referenced back by a
448
- # command rather than re-typed.
299
+ # A precondition shared across commands, declared once and referenced by name (ADR 0025).
449
300
  command "Precondition" do
450
301
  role "Language"
451
302
  goal "Declare one precondition commands can reference by name"
@@ -461,11 +312,8 @@ Hecks.bluebook "Bluebook" do
461
312
  emits PreconditionAttached
462
313
  end
463
314
 
464
- # THE LOCAL HALF OF A CROSS-AGGREGATE READ (S12, ADR 0025) — the
465
- # target's own existence and shape are checked elsewhere
466
- # (BluebookBuilder#validate_projected_fields!, once every aggregate
467
- # in the chapter is real), the same two-tier split a query's own
468
- # hop already uses.
315
+ # The local half of a cross-aggregate read. The target is checked in
316
+ # `BluebookBuilder#validate_projected_fields!` once every aggregate in the chapter exists.
469
317
  command "Projects" do
470
318
  role "Language"
471
319
  goal "Declare a field read locally through a reference"
@@ -483,9 +331,7 @@ Hecks.bluebook "Bluebook" do
483
331
  emits ProjectedFieldAttached
484
332
  end
485
333
 
486
- # HOW AGGREGATE IS SPELLED. These rows live with the concept
487
- # they describe; SyntaxBoot discovers every aggregate-local seed table.
488
- # Contexts represented here: Aggregate, Lifecycle.
334
+ # Grammar rows for the Aggregate and Lifecycle keywords; SyntaxBoot discovers them by table.
489
335
  value_object "KeywordSeed" do
490
336
  attribute :word, String
491
337
  attribute :context, String, admits: "Syntax::Context"
@@ -511,14 +357,8 @@ Hecks.bluebook "Bluebook" do
511
357
  member word: "query", context: "Aggregate", body: "keywords", inner: "Query", opens: "Query", fills: "", calls: "query_impl"
512
358
  member word: "policy", context: "Aggregate", body: "keywords", inner: "Policy", opens: "Policy", fills: "", calls: "policy_impl"
513
359
  member word: "value_object", context: "Aggregate", body: "keywords", inner: "ValueObject", opens: "ValueObject", fills: "value_objects"
514
- # THE BARE SHORTHAND — `value_object "Price", Integer`, no block:
515
- # a second row for the SAME word with `body: "none"`, the exact
516
- # two-row move `identified_by` (above) already makes for its own
517
- # block/blockless split — the body gate picks whichever row
518
- # matches how the line was actually written. Declares a value
519
- # object with exactly one attribute, named `value`, of the given
520
- # type; sugar for the block form's own single `attribute :value,
521
- # Type` line (`AggregateBuilder#value_object`'s own comment).
360
+ # Bare shorthand `value_object "Price", Integer`: a second row for the same word with
361
+ # `body: "none"`, chosen by the body gate. Declares one attribute `value` of that type.
522
362
  member word: "value_object", context: "Aggregate", body: "none", inner: "", opens: "", fills: "value_objects"
523
363
  member word: "command", context: "Aggregate", body: "keywords", inner: "Command", opens: "Command", fills: "", calls: "command_impl"
524
364
  member word: "attribute", context: "Aggregate", body: "none", inner: "", opens: "", fills: "attributes", calls: "attribute_impl"
@@ -569,13 +409,8 @@ Hecks.bluebook "Bluebook" do
569
409
  member keyword: "query", context: "Aggregate", at: "1", named: "", kind: "text", required: "true", fills: "name"
570
410
  member keyword: "policy", context: "Aggregate", at: "1", named: "", kind: "text", required: "true", fills: "name"
571
411
  member keyword: "value_object", context: "Aggregate", at: "1", named: "", kind: "text", required: "true", fills: "name"
572
- # The bare shorthand's own TYPE argument — optional, because the
573
- # block form gives no type at all (its attributes carry their own);
574
- # `kind: "constant"` for the same reason `attribute`'s own type
575
- # argument (below) is: a type is a bare constant, never quoted
576
- # text. Type-AND-block is refused by the builder itself
577
- # (`AggregateBuilder#value_object`), not here — an argument row
578
- # cannot see the body, only the call.
412
+ # The bare shorthand's type argument: optional, since the block form has none.
413
+ # Type-and-block is refused by `AggregateBuilder#value_object`; a row cannot see the body.
579
414
  member keyword: "value_object", context: "Aggregate", at: "2", named: "", kind: "constant", required: "false", fills: "type"
580
415
  member keyword: "command", context: "Aggregate", at: "1", named: "", kind: "text", required: "true", fills: "name"
581
416
  member keyword: "command", context: "Aggregate", at: "", named: "from", kind: "literal", required: "false", fills: "from"