hecks 2.8.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 (404) hide show
  1. checksums.yaml +4 -4
  2. data/exe/hecks +4 -6
  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 +17 -98
  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 +5 -48
  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 +31 -141
  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 +14 -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 +25 -31
  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 +16 -69
  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 -194
  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 -111
  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 +53 -267
  109. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +43 -305
  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 +6 -21
  114. data/lib/hecks/bluebook/model_check.rb +100 -597
  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 +4 -23
  128. data/lib/hecks/cli/document.rb +3 -21
  129. data/lib/hecks/cli/ir.rb +3 -5
  130. data/lib/hecks/cli/mcp.rb +2 -3
  131. data/lib/hecks/cli/mcp_door.rb +19 -114
  132. data/lib/hecks/cli/model_check.rb +18 -85
  133. data/lib/hecks/cli/project_cli.rb +7 -40
  134. data/lib/hecks/cli/project_diagrams.rb +0 -7
  135. data/lib/hecks/cli/run.rb +12 -58
  136. data/lib/hecks/cli/smoke_test.rb +2 -16
  137. data/lib/hecks/cli/stores.rb +1 -2
  138. data/lib/hecks/cli.rb +18 -24
  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 +82 -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 +9 -90
  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 +61 -64
  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 +6 -25
  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 +18 -124
  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 +150 -678
  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 +2 -15
  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 +42 -134
  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 +3 -6
  336. data/lib/hecks/release/runner/commands.rb +2 -4
  337. data/lib/hecks/release/runner/gem_publisher.rb +2 -3
  338. data/lib/hecks/release/runner/npm_publisher.rb +6 -20
  339. data/lib/hecks/release/runner/preflight.rb +4 -19
  340. data/lib/hecks/release/runner/tagger.rb +2 -9
  341. data/lib/hecks/release/runner.rb +3 -32
  342. data/lib/hecks/rendering.rb +4 -26
  343. data/lib/hecks/router/namespace_installer.rb +12 -36
  344. data/lib/hecks/router.rb +4 -8
  345. data/lib/hecks/runtime/aggregate_lock.rb +8 -33
  346. data/lib/hecks/runtime/boot_gates.rb +3 -18
  347. data/lib/hecks/runtime/caller.rb +19 -59
  348. data/lib/hecks/runtime/capability_graph.rb +5 -21
  349. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
  350. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
  351. data/lib/hecks/runtime/command_interpreter.rb +124 -306
  352. data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
  353. data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
  354. data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
  355. data/lib/hecks/runtime/command_rules/emission.rb +8 -21
  356. data/lib/hecks/runtime/command_rules/references.rb +23 -202
  357. data/lib/hecks/runtime/dependency_planning.rb +30 -102
  358. data/lib/hecks/runtime/dispatcher.rb +82 -241
  359. data/lib/hecks/runtime/entity_element.rb +40 -462
  360. data/lib/hecks/runtime/entity_interpreter.rb +64 -219
  361. data/lib/hecks/runtime/errors.rb +32 -115
  362. data/lib/hecks/runtime/event.rb +3 -25
  363. data/lib/hecks/runtime/identity.rb +18 -154
  364. data/lib/hecks/runtime/instance.rb +18 -150
  365. data/lib/hecks/runtime/interpreting.rb +11 -70
  366. data/lib/hecks/runtime/invocation.rb +28 -164
  367. data/lib/hecks/runtime/loader.rb +48 -186
  368. data/lib/hecks/runtime/outbox.rb +38 -261
  369. data/lib/hecks/runtime/policy_interpreter.rb +38 -200
  370. data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
  371. data/lib/hecks/runtime/query_interpreter.rb +45 -187
  372. data/lib/hecks/runtime/reaction_invocation.rb +36 -138
  373. data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
  374. data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
  375. data/lib/hecks/runtime/reference_hop.rb +8 -81
  376. data/lib/hecks/runtime/refusal_wording.rb +8 -89
  377. data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
  378. data/lib/hecks/runtime/registry/verification.rb +52 -225
  379. data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
  380. data/lib/hecks/runtime/registry.rb +99 -244
  381. data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
  382. data/lib/hecks/runtime/routing.rb +4 -15
  383. data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
  384. data/lib/hecks/runtime/saga_interpreter.rb +79 -263
  385. data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
  386. data/lib/hecks/runtime/tenant_check.rb +6 -68
  387. data/lib/hecks/runtime/tenant_scope.rb +3 -28
  388. data/lib/hecks/runtime/value/admission.rb +16 -67
  389. data/lib/hecks/runtime/value/coercion.rb +155 -641
  390. data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
  391. data/lib/hecks/runtime/value.rb +12 -84
  392. data/lib/hecks/runtime.rb +17 -65
  393. data/lib/hecks/storehouse.rb +141 -568
  394. data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
  395. data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
  396. data/lib/hecks/vendoring/git_environment.rb +2 -8
  397. data/lib/hecks/vendoring/git_source.rb +4 -10
  398. data/lib/hecks/vendoring.rb +7 -46
  399. data/lib/hecks/version.rb +3 -14
  400. data/lib/hecks.rb +26 -81
  401. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
  402. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
  403. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
  404. metadata +3 -2
@@ -3,32 +3,12 @@ require_relative "expression/ast_json"
3
3
 
4
4
  module Hecks
5
5
  module Bluebook
6
- # A field read through a `reference_to`, held locally (S12, ADR 0025
7
- # — "Consistency across aggregate boundaries") — `projects
8
- # :customer_status, from: :"customer.status"` declares that this
9
- # aggregate's own `:customer_status` is a copy of the target's own
10
- # `:status`, kept fresh by a rebuild sweep rather than read live at
11
- # rule-evaluation time. `reference` names the local reference
12
- # attribute to walk through (`:customer`, minted by this
13
- # aggregate's own `reference_to Customer`); `remote_field` names
14
- # the scalar on the target aggregate to copy.
6
+ # A field copied from a `reference_to` target, kept fresh by a rebuild sweep (S12, ADR 0025).
7
+ # `reference` is the local reference attribute to walk; `remote_field` the target's scalar.
15
8
  ProjectedField = Struct.new(:name, :reference, :remote_field, keyword_init: true)
16
9
 
17
- # A construct like every other: the aggregate carries its own identity
18
- # and sits in the owner chain between its chapter (a Bluebook) and
19
- # everything declared on it. The chain is model objects end to end —
20
- # reference resolution and hecks_fqn both walk it.
21
- #
22
- # The holding half, and nothing else. Every line below restates what
23
- # `language/bluebook/aggregate.bluebook` already declares — the field
24
- # list, said again as readers, again as constructor keywords, and
25
- # again as an emission. That triplication is what a generator removes;
26
- # `Behaviour::Aggregate` carries everything that is not derivable from
27
- # the declaration, so regenerating this file can never be lossy.
28
- #
29
- # Prototype: hand-written in the shape a generator would emit, to
30
- # prove the seam before the generator exists. `bin/project_model`
31
- # would own this file; behaviour/aggregate.rb stays hand-written.
10
+ # An aggregate: carries its own identity and sits in the owner chain below its chapter.
11
+ # The holding half only; `Behaviour::Aggregate` carries what the declaration cannot derive.
32
12
  class Aggregate
33
13
  include Construct
34
14
  include Hecks::IR
@@ -42,20 +22,10 @@ module Hecks
42
22
  value_objects: many(:value_objects),
43
23
  commands: many(:commands),
44
24
  invariants: -> { invariants.map { |rule| Expression::AstJson.rule_row(rule) } },
45
- # A precondition shared across commands, declared once (S10, ADR
46
- # 0025) — the aggregate's own named `given`s, the declaration a
47
- # referencing command's own (already-resolved) `givens` entry
48
- # came from. Both sides of "declared once, referenced many"
49
- # are real IR, the same shape a value object's type and an
50
- # attribute's own reference to it both are.
25
+ # The named `given`s a referencing command's resolved `givens` entry came from.
51
26
  preconditions: -> { preconditions.map { |rule| Expression::AstJson.rule_row(rule) } },
52
- # S12, ADR 0025 — deliberately not folded into `attributes`:
53
- # `EraGuard::ShapeDiff` only ever walks `attributes` to decide
54
- # whether a new field leaves an existing record with something
55
- # genuinely absent, and a projected field's own absence story
56
- # is different — a record predating the `projects` declaration
57
- # is expected to be missing it until the rebuild sweep runs,
58
- # not a shape drift a translation needs to explain.
27
+ # Not folded into `attributes`: EraGuard::ShapeDiff walks those, and a record predating
28
+ # `projects` is expected to lack this field until the rebuild sweep runs.
59
29
  projected_fields: lambda {
60
30
  projected_fields.map do |field|
61
31
  { name: field.name.to_s, reference: field.reference.to_s, remote_field: field.remote_field.to_s }
@@ -64,11 +34,7 @@ module Hecks
64
34
  lifecycle: one(:lifecycle),
65
35
  entities: many(:entities),
66
36
  queries: many(:queries),
67
- # Additive — every domain that declares no port emits `ports: []`,
68
- # the same "regenerate deliberately" wire-format change
69
- # ir_golden_spec.rb's own header describes; no existing key
70
- # moves. See docs/decisions (rust/project/ports.rb) for the
71
- # first reader of this.
37
+ # Additive: domains that declare no port emit `ports: []`; no existing key moves.
72
38
  ports: many(:ports),
73
39
  provenance: :provenance
74
40
  )
@@ -77,39 +43,7 @@ module Hecks
77
43
  :projected_fields, :identified_by, :identity_paths, :identity_heads, :lifecycle,
78
44
  :entities, :queries, :policies, :ports, :reference_targets, :provenance
79
45
 
80
- # Assigns what the language declares, then hands off to the
81
- # behaviour's own `settle` — derived identity, name indexes and
82
- # owner stamping, none of which the declaration states.
83
- #
84
- # @param name [String, Symbol] the aggregate's declared name
85
- # @param description [String, nil] the aggregate's declared prose description
86
- # @param attributes [Array<Bluebook::Attribute>] the aggregate's declared fields
87
- # @param value_objects [Array<Class>] the value object classes (`Bluebook::ValueObject`
88
- # subclasses) declared on this aggregate
89
- # @param commands [Array<Class>] the command classes (`Bluebook::Command` subclasses)
90
- # declared on this aggregate
91
- # @param invariants [Array<Bluebook::Invariant>] the aggregate-level rules that must
92
- # always hold
93
- # @param preconditions [Array<Bluebook::Given>] the aggregate's own named `given`s, a
94
- # referencing command's own resolved `givens` entry can point back at
95
- # @param projected_fields [Array<Bluebook::ProjectedField>] the declared `projects`
96
- # fields, copied from another aggregate's own state by the rebuild sweep
97
- # @param identified_by [String, Symbol, Array<String, Symbol>] the identity path(s)
98
- # this aggregate is addressed by
99
- # @param lifecycle [Bluebook::Lifecycle, nil] the aggregate's declared state machine,
100
- # or `nil` if it declares none
101
- # @param entities [Array<Class>] the entity classes (`Bluebook::Entity` subclasses)
102
- # nested directly under this aggregate
103
- # @param queries [Array<Bluebook::Query>] the queries declared directly on this
104
- # aggregate
105
- # @param policies [Array<Bluebook::Policy>] the reactions hoisted onto this aggregate
106
- # from the chapter that assembled it
107
- # @param ports [Array<Bluebook::DomainPort>] the aggregate-scoped ports attached after
108
- # this aggregate was built
109
- # @param reference_targets [Array<String>] the name of every aggregate this one points
110
- # at with an aggregate-level `reference_to`
111
- # @param provenance [Object, nil] the aggregate's declared canonical source, captured
112
- # exactly as written, or `nil` if it declares none
46
+ # Assigns the declared fields, then `settle` derives identity, name indexes and owner stamps.
113
47
  def initialize(name:, description: nil, attributes: [], value_objects: [],
114
48
  commands: [], invariants: [], preconditions: [], projected_fields: [], identified_by: [], lifecycle: nil,
115
49
  entities: [], queries: [], policies: [], ports: [], reference_targets: [],
@@ -1,14 +1,7 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  class Assembly
4
- # One head, built from its declaration.
5
- #
6
- # The fields come from the contract like every other construct's. What is here
7
- # is the part no field table can say: which construct holds which, and how a
8
- # head's references become able to resolve.
9
- #
10
- # It decides nothing. Whether a declaration is admissible was settled on the
11
- # way in, by the language.
4
+ # Builds one aggregate from its declaration: containment and reference resolution.
12
5
  class AggregateAssembly
13
6
  # @param row [Hash{Symbol => Object}] one declared aggregate's raw contract data,
14
7
  # as `@declaration[:aggregates]` carries it
@@ -36,10 +29,7 @@ module Hecks
36
29
  entities: entities,
37
30
  queries: asks,
38
31
  lifecycle: lifecycle_of(@row),
39
- # A policy declared inside a head is hoisted onto the chapter by the
40
- # builder, and `Aggregate#to_h` never carried it — so the language does
41
- # not record which head a chapter-level policy was written in. The
42
- # chapter holds them all, which is what `PolicyInterpreter` reads.
32
+ # Policies live on the chapter, which is what `PolicyInterpreter` reads.
43
33
  policies: [],
44
34
  reference_targets: reference_targets(fields)
45
35
  )
@@ -50,12 +40,7 @@ module Hecks
50
40
 
51
41
  private
52
42
 
53
- # What this head points at with an aggregate-level `reference_to`. Not the
54
- # self-references its verbs carry — the first version read
55
- # `commands.filter_map(&:references)` and gave Pizza two targets of "Pizza",
56
- # its own verbs pointing at itself, where the builder recorded none. An
57
- # aggregate-level `reference_to X` leaves a reference attribute behind, so
58
- # the attributes are where the answer is.
43
+ # Read from attributes, not commands: a command's self-references are not targets.
59
44
  def reference_targets(fields)
60
45
  fields.select(&:reference?).map { |field| field.type.target_name }
61
46
  end
@@ -64,12 +49,7 @@ module Hecks
64
49
  Build.call("ValueObject", row)
65
50
  end
66
51
 
67
- # S17, ADR 0026 — recurses. "That is what `entity` is for, and
68
- # `entity` is declared by the language and used zero times in it"
69
- # — Dispatch, inside Handler, is the first use, so `row[:entities]`
70
- # is built the same way `row` itself was reached: through this
71
- # same method, one level deeper each time. Nothing here assumes
72
- # it stops at one level of nesting.
52
+ # Recurses, so entities nest to any depth (ADR 0026).
73
53
  def entity(row)
74
54
  Build.call(
75
55
  "Entity", row,
@@ -80,10 +60,8 @@ module Hecks
80
60
  )
81
61
  end
82
62
 
83
- # Every reference learns which head declares it, so it can reach the chapter
84
- # and resolve. Deliberately across every list that can carry one — a
85
- # reference the walk misses resolves to nil, and a nil target is skipped
86
- # rather than refused, so the guarantee would go quiet instead of red.
63
+ # Must cover every list that can carry a reference: a missed one resolves to nil,
64
+ # and a nil target is skipped rather than refused.
87
65
  def stamp_references(aggregate)
88
66
  lists = [aggregate.attributes, *aggregate.commands.map(&:attributes), *aggregate.queries.map(&:attributes)]
89
67
  entity_reference_lists(aggregate.entities, lists)
@@ -91,8 +69,6 @@ module Hecks
91
69
  lists.flatten.select(&:reference?).each { |field| field.type.declared_in = aggregate }
92
70
  end
93
71
 
94
- # S17, ADR 0026 — walks nested entities too (Dispatch, inside
95
- # Handler), not only an aggregate's own direct ones.
96
72
  def entity_reference_lists(entities, lists)
97
73
  entities.each do |piece|
98
74
  lists << piece.attributes
@@ -102,9 +78,7 @@ module Hecks
102
78
  end
103
79
  end
104
80
 
105
- # Three language fields, one IR object. `state_field`, `state_start` and
106
- # `transitions` are separate declarations; the IR keeps one Lifecycle. The
107
- # contract names them derived, and this is what derives them.
81
+ # Folds `state_field`, `state_start` and `transitions` into the IR's one Lifecycle.
108
82
  def lifecycle_of(row)
109
83
  declared = row[:lifecycle]
110
84
  return nil unless declared
@@ -116,11 +90,8 @@ module Hecks
116
90
  )
117
91
  end
118
92
 
119
- # A lifecycle holds [command, StateTransition] pairs and `to_h` expands one
120
- # pair whose `from` is a list into several rows. Grouped back by command and
121
- # target, because one declared pair has exactly one target and may have many
122
- # froms — grouping by command alone would fuse two declarations that move the
123
- # same verb to different states.
93
+ # Regroups `to_h` rows by command and target; grouping by command alone would fuse
94
+ # declarations that move one verb to different states.
124
95
  def transitions(rows)
125
96
  rows.group_by { |move| [move[:command], move[:to_state]] }
126
97
  .map do |(command, target), moves|
@@ -1,18 +1,9 @@
1
1
  module Hecks
2
2
  module Bluebook
3
3
  class Assembly
4
- # One way to build a construct, for every construct.
4
+ # Builds any construct from its declared row by reading its `Assembly.contract`.
5
5
  #
6
- # Not a method per category — `value_object(row)`, `command(row)`,
7
- # `policy(row)`, each gathering the same keywords the contract already
8
- # names. This reads the contract instead, so adding a field to the
9
- # language and forgetting to assemble it is caught by the coverage gate
10
- # rather than by nobody.
11
- #
12
- # `make` is the only branch, and it is a real one: a construct that became a
13
- # class is `.declare`d, an instance is `.new`ed. That is the boundary
14
- # `Query` sits on, and it is a fact about Ruby rather than about the
15
- # domain.
6
+ # A construct that is a class is `.declare`d; an instance is `.new`ed.
16
7
  module Build
17
8
  module_function
18
9
 
@@ -42,8 +33,7 @@ module Hecks
42
33
  contract.holder or raise ArgumentError, "#{contract} holds nothing that can be built"
43
34
  end
44
35
 
45
- # A reader is a Marks method, a list of them, or one of three spellings that
46
- # need no decoding at all.
36
+ # Reads one value through a contract reader.
47
37
  #
48
38
  # @param reader [Symbol, Array, nil] the contract field's reader: `:plain`,
49
39
  # `:identity`, `:flag`, `[:each, marks_method]`, `[:option, name]`, or a bare
@@ -56,8 +46,7 @@ module Hecks
56
46
  when :identity then value&.to_sym
57
47
  when :flag then value ? true : false
58
48
  when Array
59
- # [:each, reader] maps a list ; [:option, name] reads one named option,
60
- # which needs its name as well as its value.
49
+ # `[:option, name]` needs its name as well as its value.
61
50
  if reader.first == :each
62
51
  Array(value).map { |held| Marks.public_send(reader.last, held) }
63
52
  else
@@ -1,94 +1,26 @@
1
1
  module Hecks
2
2
  module Bluebook
3
- # The rulebook translating between the language's own declarations and the
4
- # IR objects `Build`/`Reconstruction` produce from them — the `Contract`
5
- # struct format itself (this file) plus, reopened in contracts.rb, the
6
- # `CONTRACTS` table of one `Contract` per construct category.
3
+ # Translates the language's declarations into the IR that `Build` and
4
+ # `Reconstruction` produce; `CONTRACTS` (contracts.rb) holds one per category.
7
5
  class Assembly
8
- # What a construct needs that the language cannot say, and how a claim that a
9
- # field needs no assembling is checked.
10
- #
11
- # Naming a field derived is a claim, and a claim needs a kind, not just a name
12
- # in a list. A bare list of names is a promise with nobody holding it: the
13
- # coverage gate only asks whether a field is accounted for, so `derived:
14
- # %i[version]` would satisfy it while dropping a chapter's version in
15
- # silence — the exact shape of every defect this arc has found.
16
- #
17
- # :parent the containment tree supplies it — a `*_id`, or one of
18
- # the named pointers below. Checked against the name.
19
- # :children it is assembled as child constructs. Checked against the
20
- # language: a category must exist whose parent is this one.
21
- # [:computed, :m] the holder works it out. Checked: it must answer to `m`.
22
- # [:folded, keys] several language fields are one thing in the IR, or one
23
- # is spread across several. Checked: every key must appear
24
- # in a real reconstructed declaration.
25
- # :elsewhere not a fact about this construct at all. Allow-listed one
26
- # by one, because it is the kind with no other check.
27
- #
28
- # Every one of those can fail. That is the whole difference.
6
+ # A derived claim's kind is one of :parent, :children, [:computed, method],
7
+ # [:folded, keys], or :elsewhere — each checked structurally, not just named.
29
8
  Contract = Struct.new(:holder, :make, :fields, :derived, :rows, :reads, keyword_init: true) do
30
- # How a declaration key is read back off a row. Absent means the default —
31
- # `text(row[key])`, a single cell — which is most of them ; present names the
32
- # shape, because a list needs a reader per element and a folded field is
33
- # gathered rather than fetched. Same pattern as `rows`, in the other
34
- # direction: declare the exceptions, default the rest.
35
- #
36
- # @param key [String, Symbol] the field's declaration key, as `fields` names it
37
- # @return [Symbol, Array, nil] the reader named in `reads` for `key`, or `nil`
38
- # when the field reads through the default single-cell reader
9
+ # nil means the field reads through the default single-cell reader.
39
10
  def reader(key) = Hash(reads)[key.to_sym]
40
11
 
41
- # How an appendable list becomes rows the walk can offer. A list absent from
42
- # here reads straight off the node ; one that is present names the shaper,
43
- # because the IR keeps a shape the language does not — a transition whose
44
- # `from` is a list is several rows, an append binds several fields at once,
45
- # an open map is one row per entry.
46
- #
47
- # @param list [String, Symbol] the appendable list's field name
48
- # @return [Symbol, nil] the shaper method named in `rows` for `list`, or `nil`
49
- # when the list reads straight off the node instead
12
+ # nil means the list reads straight off the node.
50
13
  def shaper(list) = Hash(rows)[list.to_sym]
51
14
 
52
- # Whether `field` is one this contract accounts for, stored or derived.
53
- #
54
- # @param field [Symbol] the field name to check
55
- # @return [Boolean] whether `field` is a key of `fields` or of `derived`
56
15
  def declares?(field) = fields.key?(field) || derived.key?(field)
57
16
 
58
- # Names the kind of derived claim `field` makes, if any.
59
- #
60
- # @param field [Symbol] the derived field name to check
61
- # @return [Symbol, Array, nil] the kind `derived` names for `field` — `:parent`,
62
- # `:children`, `:elsewhere`, `:walk`, an `[:computed, method]` or `[:folded,
63
- # object, member]` pair — or `nil` when `field` is not derived
64
17
  def kind_of(field) = derived[field]
65
18
 
66
- # The fields the walk supplies — every `derived: { field => :walk }` claim.
67
- # The language declares them (`attribute :position, Position`) so the
68
- # judge can order siblings, but no constructor takes one. This is the one
69
- # place that fact is stated ; `Specializer` and `Model::Deviations` read it
70
- # here rather than each keeping their own `%i[position]`.
71
- #
72
- # @return [Array<Symbol>] every field name whose derived kind is `:walk`
19
+ # Every derived field the walk supplies; Specializer skips these.
73
20
  def walked = derived.select { |_field, kind| kind == :walk }.keys
74
21
 
75
- # Where a folded field actually lives, as [object, member].
76
- #
77
- # `[:folded, :lifecycle, :field]` says the language's `state_field` is the
78
- # `field` of the IR's one Lifecycle. `Readings` would otherwise have to state
79
- # that fact a second time as `node.lifecycle&.field` — saying it once here
80
- # drives both directions instead: the walk reads the member on the way in, and
81
- # the reconstruction gathers the members back into the object on the way out.
82
- #
83
- # A nil member means the fold has no single member to name — `rows` is a
84
- # count of what `closed_set` and `members` hold between them, and `options`
85
- # spreads across eight keys. Those keep their own code, and the gate still
86
- # checks the object they name is real.
87
- #
88
- # @param field [Symbol] the derived field name to check
89
- # @return [Array(Symbol, Symbol), Array(Array<Symbol>, nil), nil] the `[object,
90
- # member]` pair the field folds into — `member` is `nil` when the fold has
91
- # no single member to name — or `nil` when `field` does not fold at all
22
+ # [object, member] a folded field lives at; member is nil when the fold
23
+ # has no single one to name (e.g. a count plus a list of rows).
92
24
  def folded(field)
93
25
  kind = derived[field]
94
26
  return nil unless kind.is_a?(Array) && kind.first == :folded
@@ -96,20 +28,8 @@ module Hecks
96
28
  [kind[1], kind[2]]
97
29
  end
98
30
 
99
- # Computed means worked out, not merely answerable.
100
- #
101
- # Asking only whether the holder responds was too weak, and measurably so:
102
- # `[:computed, :version]` passed, because `Bluebook` does answer to
103
- # `version` — it just answers with what the constructor was handed. A field
104
- # the constructor takes is stored, and calling it computed is how a chapter's
105
- # version would have gone missing while the gate said yes.
106
- #
107
- # So a computed field is one the holder answers and the constructor does not
108
- # accept. `query_name` qualifies (`Naming.snake(name)`) ; `version` cannot.
109
- #
110
- # @param method [Symbol] the field name to check
111
- # @return [Boolean] whether `holder` answers `method` but its constructor does
112
- # not accept it as a keyword
31
+ # Computed means the holder answers but its constructor won't accept it —
32
+ # respond_to? alone would also count a stored field like `version`.
113
33
  def computes?(method)
114
34
  return false unless holder
115
35
  return false unless answers?(method)
@@ -117,22 +37,10 @@ module Hecks
117
37
  !accepts?(method)
118
38
  end
119
39
 
120
- # Whether `holder` answers `method`, checked the way that fits how it is
121
- # built: `respond_to?` for a `:declare` holder (a class, queried live) and
122
- # `method_defined?` for a `:new` holder (an instance method, checked without
123
- # building one).
124
- #
125
- # @param method [Symbol] the method name to check
126
- # @return [Boolean] whether `holder` answers `method`
127
40
  def answers?(method)
128
41
  make == :declare ? holder.respond_to?(method) : holder.method_defined?(method)
129
42
  end
130
43
 
131
- # Whether the holder's constructor takes `keyword` as a keyword argument.
132
- #
133
- # @param keyword [Symbol] the keyword to check
134
- # @return [Boolean] whether the holder's constructor (`.declare` or
135
- # `#initialize`) accepts `keyword` as an optional or required keyword
136
44
  def accepts?(keyword)
137
45
  builder = make == :declare ? holder.method(:declare) : holder.instance_method(:initialize)
138
46
 
@@ -140,49 +48,20 @@ module Hecks
140
48
  end
141
49
  end
142
50
 
143
- # The fields that point at a parent without being spelled `*_id` — the one list,
144
- # read by the assembly gate (a `:parent` claim), the model generator and
145
- # QueryIR (a declared field the model composes instead of storing).
146
- #
147
- # aggregate, bluebook the bare parent link a creating command mints
148
- # (ADR 0025) — exactly the `parent_key`s `Plan` reads
149
- # off the language
150
- # owner Entity's own text twin of that link, which is why
151
- # Entity's contract claims `owner: :parent`
152
- #
153
- # `shape` and `handler` are not on this list — S17 (ADR 0026) made Member and
154
- # Dispatch nested entities, so neither is a parent field the way
155
- # `owner` is. `spec/assembly_spec` derives this set from `Plan` and the
156
- # contracts directly and fails on any drift, rather than trusting this list to
157
- # stay in sync with a second hand-written copy kept by the model generator.
51
+ # Parent-pointer fields that don't end in `_id` (ADR 0025).
52
+ # spec/assembly_spec derives this set independently and fails on drift.
158
53
  PARENT_POINTERS = %i[aggregate bluebook owner].freeze
159
54
 
160
- # Whether `field` is a parent pointer that does not end in `_id`.
161
- #
162
- # @param field [String, Symbol] the field name to check
163
- # @return [Boolean] whether `field` ends with `_id`, or is one of
164
- # `PARENT_POINTERS`
165
55
  def self.parent_pointer?(field)
166
56
  field.to_s.end_with?("_id") || PARENT_POINTERS.include?(field.to_sym)
167
57
  end
168
58
 
169
- # The only fields allowed to claim they describe something other than the
170
- # construct they hang off, each with the reason spelled out.
171
- #
172
- # normalisations the canonical-form table belongs to the expression grammar.
173
- # A chapter's rules are canonicalised on the way in, so the
174
- # language models the table — but no chapter stores one, and
175
- # `Bluebook#to_h` splices it in from Expression.
59
+ # Fields allowed to describe something other than their own construct.
60
+ # `Bluebook.normalisations` belongs to the expression grammar; `to_h` splices it in.
176
61
  ELSEWHERE = {
177
62
  Bluebook: %i[normalisations]
178
63
  }.freeze
179
64
 
180
- # Whether `field` is allow-listed as describing something other than
181
- # `category`'s own construct — see `ELSEWHERE`.
182
- #
183
- # @param category [String, Symbol] the construct category name
184
- # @param field [Symbol] the field name to check
185
- # @return [Boolean] whether `field` is on `category`'s `ELSEWHERE` entry
186
65
  def self.elsewhere?(category, field)
187
66
  Array(ELSEWHERE[category.to_sym]).include?(field)
188
67
  end