hecks 1.3.0 → 1.4.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 (355) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/claude_code.rb +7 -7
  3. data/lib/hecks/adapters/driven/d1.rb +187 -23
  4. data/lib/hecks/adapters/driven/folder.rb +10 -10
  5. data/lib/hecks/adapters/driven/google_authentication.rb +8 -8
  6. data/lib/hecks/adapters/driven/governance_authorization.rb +31 -13
  7. data/lib/hecks/adapters/driven/heki/journal.rb +5 -4
  8. data/lib/hecks/adapters/driven/heki/saga_store.rb +5 -5
  9. data/lib/hecks/adapters/driven/heki.rb +13 -7
  10. data/lib/hecks/adapters/driven/identity_registry.rb +2 -2
  11. data/lib/hecks/adapters/driven/in_memory_ordering.rb +3 -3
  12. data/lib/hecks/adapters/driven/lambda/client.rb +34 -9
  13. data/lib/hecks/adapters/driven/lambda.rb +39 -33
  14. data/lib/hecks/adapters/driven/local_storage.rb +17 -10
  15. data/lib/hecks/adapters/driven/memory.rb +205 -9
  16. data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +1 -1
  17. data/lib/hecks/adapters/driven/postgres/codec.rb +27 -11
  18. data/lib/hecks/adapters/driven/postgres/outbox.rb +40 -2
  19. data/lib/hecks/adapters/driven/postgres/reconnect.rb +23 -7
  20. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +14 -14
  21. data/lib/hecks/adapters/driven/postgres.rb +175 -28
  22. data/lib/hecks/adapters/driven/prism.rb +4 -4
  23. data/lib/hecks/adapters/driven/sql_query_builder.rb +34 -22
  24. data/lib/hecks/adapters/driven/sqlite/codec.rb +38 -10
  25. data/lib/hecks/adapters/driven/sqlite/projection.rb +60 -32
  26. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +12 -12
  27. data/lib/hecks/adapters/driven/sqlite.rb +181 -21
  28. data/lib/hecks/adapters/driven.rb +4 -4
  29. data/lib/hecks/adapters/driving/github_webhook.rb +18 -18
  30. data/lib/hecks/behaviors/dsl.rb +2 -2
  31. data/lib/hecks/behaviors/expectations.rb +23 -23
  32. data/lib/hecks/behaviors/ir.rb +1 -1
  33. data/lib/hecks/behaviors/rspec.rb +1 -1
  34. data/lib/hecks/behaviors/runner.rb +2 -2
  35. data/lib/hecks/behaviors.rb +1 -1
  36. data/lib/hecks/bluebook/aggregate.rb +13 -13
  37. data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +10 -10
  38. data/lib/hecks/bluebook/assembly/build.rb +1 -1
  39. data/lib/hecks/bluebook/assembly/contract.rb +39 -16
  40. data/lib/hecks/bluebook/assembly/contracts.rb +40 -38
  41. data/lib/hecks/bluebook/assembly/marks.rb +18 -18
  42. data/lib/hecks/bluebook/assembly/specializer.rb +19 -21
  43. data/lib/hecks/bluebook/assembly.rb +9 -9
  44. data/lib/hecks/bluebook/attribute.rb +9 -9
  45. data/lib/hecks/bluebook/behaviour/aggregate.rb +11 -11
  46. data/lib/hecks/bluebook/behaviour/attribute.rb +5 -5
  47. data/lib/hecks/bluebook/behaviour/chapter.rb +23 -5
  48. data/lib/hecks/bluebook/behaviour/command.rb +23 -23
  49. data/lib/hecks/bluebook/behaviour/domain_port.rb +7 -7
  50. data/lib/hecks/bluebook/behaviour/entity.rb +8 -8
  51. data/lib/hecks/bluebook/behaviour/hexagon.rb +4 -4
  52. data/lib/hecks/bluebook/behaviour/lifecycle.rb +5 -5
  53. data/lib/hecks/bluebook/behaviour/policy.rb +12 -12
  54. data/lib/hecks/bluebook/behaviour/process_manager.rb +7 -7
  55. data/lib/hecks/bluebook/behaviour/query.rb +1 -1
  56. data/lib/hecks/bluebook/behaviour/read_model.rb +8 -8
  57. data/lib/hecks/bluebook/behaviour/traits.rb +12 -12
  58. data/lib/hecks/bluebook/behaviour/value_object.rb +6 -6
  59. data/lib/hecks/bluebook/capabilities.rb +27 -0
  60. data/lib/hecks/bluebook/chapter.rb +28 -9
  61. data/lib/hecks/bluebook/command.rb +12 -12
  62. data/lib/hecks/bluebook/domain_port.rb +9 -9
  63. data/lib/hecks/bluebook/dsl/adapter_builder.rb +24 -0
  64. data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +49 -49
  65. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +96 -96
  66. data/lib/hecks/bluebook/dsl/attribute_collector.rb +41 -41
  67. data/lib/hecks/bluebook/dsl/binding_proxy.rb +22 -2
  68. data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +111 -74
  69. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +48 -30
  70. data/lib/hecks/bluebook/dsl/bootstrap_table.rb +116 -0
  71. data/lib/hecks/bluebook/dsl/command_builder.rb +103 -103
  72. data/lib/hecks/bluebook/dsl/const_shim.rb +46 -15
  73. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +90 -25
  74. data/lib/hecks/bluebook/dsl/entity_builder.rb +56 -56
  75. data/lib/hecks/bluebook/dsl/generic_dispatch.rb +148 -132
  76. data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +89 -30
  77. data/lib/hecks/bluebook/dsl/identity_declaration.rb +17 -17
  78. data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +27 -4
  79. data/lib/hecks/bluebook/dsl/policy_builder.rb +30 -21
  80. data/lib/hecks/bluebook/dsl/port_builder.rb +38 -7
  81. data/lib/hecks/bluebook/dsl/port_operation_builder.rb +56 -22
  82. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +35 -35
  83. data/lib/hecks/bluebook/dsl/query_builder.rb +5 -5
  84. data/lib/hecks/bluebook/dsl/read_model_builder.rb +34 -34
  85. data/lib/hecks/bluebook/dsl/rule_reference.rb +41 -39
  86. data/lib/hecks/bluebook/dsl/translation_builder.rb +9 -9
  87. data/lib/hecks/bluebook/dsl/value_object_builder.rb +16 -16
  88. data/lib/hecks/bluebook/dsl/word_gate.rb +59 -53
  89. data/lib/hecks/bluebook/dsl/world_builder.rb +51 -8
  90. data/lib/hecks/bluebook/entity.rb +11 -11
  91. data/lib/hecks/bluebook/expression/ast_json.rb +20 -20
  92. data/lib/hecks/bluebook/expression/ast_reader.rb +3 -3
  93. data/lib/hecks/bluebook/expression/canonical_form.rb +9 -9
  94. data/lib/hecks/bluebook/expression/evaluator.rb +18 -18
  95. data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +18 -18
  96. data/lib/hecks/bluebook/expression/resolver.rb +60 -62
  97. data/lib/hecks/bluebook/hexagon.rb +1 -1
  98. data/lib/hecks/bluebook/lifecycle.rb +1 -1
  99. data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -1
  100. data/lib/hecks/bluebook/meta_validator/judge.rb +101 -87
  101. data/lib/hecks/bluebook/meta_validator/plan.rb +39 -39
  102. data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -2
  103. data/lib/hecks/bluebook/meta_validator/readings.rb +43 -43
  104. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +44 -37
  105. data/lib/hecks/bluebook/meta_validator/shapes.rb +25 -21
  106. data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +145 -31
  107. data/lib/hecks/bluebook/meta_validator/translation_judge.rb +6 -6
  108. data/lib/hecks/bluebook/meta_validator/world_judge.rb +5 -5
  109. data/lib/hecks/bluebook/meta_validator.rb +70 -70
  110. data/lib/hecks/bluebook/model_check.rb +170 -84
  111. data/lib/hecks/bluebook/pattern_subset.rb +9 -9
  112. data/lib/hecks/bluebook/policy.rb +15 -13
  113. data/lib/hecks/bluebook/process_manager.rb +14 -14
  114. data/lib/hecks/bluebook/project_register.rb +6 -6
  115. data/lib/hecks/bluebook/query.rb +4 -4
  116. data/lib/hecks/bluebook/read_model.rb +14 -14
  117. data/lib/hecks/bluebook/reference.rb +8 -8
  118. data/lib/hecks/bluebook/smoke_test.rb +19 -19
  119. data/lib/hecks/bluebook/synthesizer.rb +12 -12
  120. data/lib/hecks/bluebook/translation.rb +4 -4
  121. data/lib/hecks/bluebook/value_object.rb +6 -6
  122. data/lib/hecks/bluebook.rb +2 -2
  123. data/lib/hecks/codemod/legacy_dispatch_args.rb +299 -0
  124. data/lib/hecks/codemod/legacy_dispatch_recorder.rb +186 -0
  125. data/lib/hecks/codemod.rb +36 -35
  126. data/lib/hecks/construct.rb +6 -6
  127. data/lib/hecks/corpus.rb +317 -0
  128. data/lib/hecks/deprecation.rb +95 -0
  129. data/lib/hecks/doc/reference.rb +19 -19
  130. data/lib/hecks/embryonaut_bluebook.rb +11 -11
  131. data/lib/hecks/facade/cli_door.rb +69 -10
  132. data/lib/hecks/facade/cli_runner.rb +105 -24
  133. data/lib/hecks/facade/command_request.rb +23 -0
  134. data/lib/hecks/facade/handle.rb +79 -32
  135. data/lib/hecks/facade/json_door.rb +106 -25
  136. data/lib/hecks/facade/surface/aggregate_door.rb +42 -27
  137. data/lib/hecks/facade/surface/chapter.rb +26 -17
  138. data/lib/hecks/facade/surface.rb +16 -3
  139. data/lib/hecks/facade.rb +15 -4
  140. data/lib/hecks/forms/app.rb +46 -30
  141. data/lib/hecks/forms/command_form_renderer.rb +70 -9
  142. data/lib/hecks/forms/field_renderer.rb +142 -6
  143. data/lib/hecks/forms/field_shape.rb +180 -19
  144. data/lib/hecks/forms/html.rb +51 -7
  145. data/lib/hecks/forms/index_renderer.rb +14 -2
  146. data/lib/hecks/forms/params.rb +120 -23
  147. data/lib/hecks/forms/port_argument.rb +2 -2
  148. data/lib/hecks/forms/query_form_renderer.rb +2 -2
  149. data/lib/hecks/forms/record_renderer.rb +2 -2
  150. data/lib/hecks/forms/record_table.rb +1 -1
  151. data/lib/hecks/forms/value_object_shape.rb +3 -3
  152. data/lib/hecks/forms.rb +24 -4
  153. data/lib/hecks/fqn.rb +1 -1
  154. data/lib/hecks/framework/bluebook/governance.bluebook +9 -0
  155. data/lib/hecks/framework.rb +48 -17
  156. data/lib/hecks/freezer.rb +11 -11
  157. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +90 -90
  158. data/lib/hecks/fuzzing/combination_miner.rb +119 -0
  159. data/lib/hecks/fuzzing/concurrent_dispatch.rb +140 -45
  160. data/lib/hecks/fuzzing/coverage_campaign.rb +118 -0
  161. data/lib/hecks/fuzzing/differential.rb +158 -0
  162. data/lib/hecks/fuzzing/domain_generator.rb +694 -0
  163. data/lib/hecks/fuzzing/era_boundary.rb +37 -18
  164. data/lib/hecks/fuzzing/form_census.rb +35 -20
  165. data/lib/hecks/fuzzing/generated_domain_check.rb +95 -0
  166. data/lib/hecks/fuzzing/invalid_value_generator.rb +6 -6
  167. data/lib/hecks/fuzzing/isolated_boot.rb +62 -62
  168. data/lib/hecks/fuzzing/nondeterministic.rb +67 -0
  169. data/lib/hecks/fuzzing/persistence_parity.rb +19 -21
  170. data/lib/hecks/fuzzing/properties/corrections.rb +9 -9
  171. data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +154 -49
  172. data/lib/hecks/fuzzing/properties/guards.rb +42 -42
  173. data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +32 -32
  174. data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +22 -35
  175. data/lib/hecks/fuzzing/properties/outbox.rb +24 -24
  176. data/lib/hecks/fuzzing/properties/querying.rb +17 -17
  177. data/lib/hecks/fuzzing/properties.rb +64 -40
  178. data/lib/hecks/fuzzing/qa_settings.rb +152 -0
  179. data/lib/hecks/fuzzing/replay.rb +114 -114
  180. data/lib/hecks/fuzzing/rotation_priority.rb +10 -10
  181. data/lib/hecks/fuzzing/rust_gap_manifest.rb +113 -0
  182. data/lib/hecks/fuzzing/self_consistency.rb +141 -112
  183. data/lib/hecks/fuzzing/sequence_generator/adversary.rb +35 -35
  184. data/lib/hecks/fuzzing/sequence_generator/catalog.rb +18 -11
  185. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +13 -12
  186. data/lib/hecks/fuzzing/sequence_generator/picker.rb +21 -12
  187. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +58 -31
  188. data/lib/hecks/fuzzing/sequence_generator.rb +111 -23
  189. data/lib/hecks/fuzzing/shrinker.rb +197 -0
  190. data/lib/hecks/fuzzing/structural_skips.rb +23 -130
  191. data/lib/hecks/fuzzing/sweep_depth.rb +4 -4
  192. data/lib/hecks/fuzzing/target_capabilities.rb +49 -18
  193. data/lib/hecks/fuzzing/value_generator.rb +14 -14
  194. data/lib/hecks/fuzzing.rb +5 -0
  195. data/lib/hecks/grammar/evolve.rb +10 -10
  196. data/lib/hecks/grammar.rb +7 -7
  197. data/lib/hecks/ir.rb +13 -13
  198. data/lib/hecks/language/bluebook/bluebook.bluebook +41 -0
  199. data/lib/hecks/language/bluebook/policy.bluebook +11 -1
  200. data/lib/hecks/language/bluebook/vocabulary.bluebook +348 -13
  201. data/lib/hecks/language/oidc.json +5 -0
  202. data/lib/hecks/literal.rb +9 -9
  203. data/lib/hecks/naming.rb +25 -25
  204. data/lib/hecks/ports/access_control.rb +58 -2
  205. data/lib/hecks/ports/agent/answers.rb +83 -6
  206. data/lib/hecks/ports/agent.rb +119 -35
  207. data/lib/hecks/ports/authentication.rb +44 -4
  208. data/lib/hecks/ports/authorization.rb +53 -11
  209. data/lib/hecks/ports/clock.rb +42 -23
  210. data/lib/hecks/ports/extraction.rb +16 -0
  211. data/lib/hecks/ports/identity_assignment.rb +24 -2
  212. data/lib/hecks/ports/identity_generation.rb +17 -3
  213. data/lib/hecks/ports/identity_resolution.rb +18 -1
  214. data/lib/hecks/ports/loading.rb +4 -0
  215. data/lib/hecks/ports/persistence/append_only.rb +172 -8
  216. data/lib/hecks/ports/persistence/binding_policy.rb +34 -0
  217. data/lib/hecks/ports/persistence/codec_boundary.rb +178 -0
  218. data/lib/hecks/ports/persistence/execution.rb +4 -0
  219. data/lib/hecks/ports/persistence/null_saga_store.rb +12 -1
  220. data/lib/hecks/ports/persistence/plugin.rb +42 -4
  221. data/lib/hecks/ports/persistence/plugins/era/era_check.rb +218 -25
  222. data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +77 -9
  223. data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +81 -24
  224. data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +29 -18
  225. data/lib/hecks/ports/persistence/plugins/era/lineage.rb +144 -60
  226. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +103 -8
  227. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +98 -23
  228. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +282 -109
  229. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +63 -25
  230. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +118 -66
  231. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +51 -28
  232. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +28 -5
  233. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +25 -12
  234. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +129 -34
  235. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +51 -6
  236. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +33 -9
  237. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +16 -0
  238. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +57 -4
  239. data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +25 -2
  240. data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +314 -90
  241. data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +68 -10
  242. data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +9 -3
  243. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +9 -2
  244. data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +42 -8
  245. data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +16 -1
  246. data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +36 -5
  247. data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +23 -3
  248. data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -19
  249. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +5 -5
  250. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +1 -1
  251. data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -2
  252. data/lib/hecks/ports/persistence/plugins/era.rb +12 -2
  253. data/lib/hecks/ports/persistence/remote_runtime.rb +9 -2
  254. data/lib/hecks/ports/persistence/repository_factory.rb +23 -3
  255. data/lib/hecks/ports/persistence/state_codec.rb +319 -0
  256. data/lib/hecks/ports/persistence.rb +36 -1
  257. data/lib/hecks/ports/projection.rb +61 -7
  258. data/lib/hecks/ports/query/in_memory.rb +3 -3
  259. data/lib/hecks/ports/query/ordering.rb +6 -6
  260. data/lib/hecks/ports/query.rb +35 -0
  261. data/lib/hecks/projections/bootstrap_table.rb +112 -0
  262. data/lib/hecks/projections/diagrams.rb +75 -75
  263. data/lib/hecks/projections/glossary/html.rb +3 -3
  264. data/lib/hecks/projections/glossary/markdown.rb +3 -3
  265. data/lib/hecks/projections/glossary/mermaid.rb +1 -1
  266. data/lib/hecks/projections/glossary/sections.rb +1 -1
  267. data/lib/hecks/projections/glossary/sentences.rb +5 -5
  268. data/lib/hecks/projections/glossary.rb +15 -15
  269. data/lib/hecks/projections/ir.rb +1 -1
  270. data/lib/hecks/projections/model/deviations.rb +18 -17
  271. data/lib/hecks/projections/model.rb +25 -21
  272. data/lib/hecks/projections/oidc.rb +7 -7
  273. data/lib/hecks/projections/parser_table.rb +5 -5
  274. data/lib/hecks/projections/reference.rb +3 -3
  275. data/lib/hecks/projections/rust_vocabulary.rb +443 -0
  276. data/lib/hecks/projections/shape.rb +2 -2
  277. data/lib/hecks/projections/statements.rb +11 -11
  278. data/lib/hecks/projections/vocabulary.rb +9 -9
  279. data/lib/hecks/projections.rb +5 -3
  280. data/lib/hecks/projector/cli_projector.rb +29 -29
  281. data/lib/hecks/projector/docs_projector.rb +13 -13
  282. data/lib/hecks/projector/exporter.rb +42 -21
  283. data/lib/hecks/projector/ir_projector.rb +1 -1
  284. data/lib/hecks/projector/narrate_projector.rb +11 -11
  285. data/lib/hecks/projector/target.rb +13 -13
  286. data/lib/hecks/projector.rb +15 -15
  287. data/lib/hecks/query_ir.rb +47 -47
  288. data/lib/hecks/query_specification/common/comparators.rb +19 -3
  289. data/lib/hecks/query_specification/common/comparison.rb +109 -27
  290. data/lib/hecks/query_specification/common/dsl.rb +65 -9
  291. data/lib/hecks/query_specification/common/null_policy.rb +57 -13
  292. data/lib/hecks/query_specification/common/null_semantics.rb +4 -0
  293. data/lib/hecks/query_specification/common/options.rb +25 -0
  294. data/lib/hecks/query_specification/field_path.rb +69 -15
  295. data/lib/hecks/query_specification/hop_path.rb +57 -20
  296. data/lib/hecks/query_specification/read_model/specification.rb +4 -0
  297. data/lib/hecks/rendering.rb +3 -3
  298. data/lib/hecks/router/namespace_installer.rb +3 -3
  299. data/lib/hecks/router.rb +1 -1
  300. data/lib/hecks/runtime/aggregate_lock.rb +11 -11
  301. data/lib/hecks/runtime/boot_gates.rb +3 -3
  302. data/lib/hecks/runtime/caller.rb +8 -8
  303. data/lib/hecks/runtime/capability_graph.rb +2 -2
  304. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +22 -25
  305. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +42 -63
  306. data/lib/hecks/runtime/command_interpreter.rb +159 -102
  307. data/lib/hecks/runtime/command_rules/admissibility.rb +69 -69
  308. data/lib/hecks/runtime/command_rules/arithmetic.rb +137 -91
  309. data/lib/hecks/runtime/command_rules/authorization.rb +38 -17
  310. data/lib/hecks/runtime/command_rules/emission.rb +18 -1
  311. data/lib/hecks/runtime/command_rules/references.rb +35 -35
  312. data/lib/hecks/runtime/command_rules.rb +3 -0
  313. data/lib/hecks/runtime/dependency_planning.rb +11 -11
  314. data/lib/hecks/runtime/dispatcher.rb +283 -90
  315. data/lib/hecks/runtime/entity_element.rb +151 -67
  316. data/lib/hecks/runtime/entity_interpreter.rb +108 -82
  317. data/lib/hecks/runtime/errors.rb +19 -19
  318. data/lib/hecks/runtime/event.rb +6 -6
  319. data/lib/hecks/runtime/identity.rb +22 -22
  320. data/lib/hecks/runtime/instance.rb +39 -14
  321. data/lib/hecks/runtime/interpreting.rb +12 -12
  322. data/lib/hecks/runtime/invocation.rb +276 -0
  323. data/lib/hecks/runtime/loader.rb +14 -14
  324. data/lib/hecks/runtime/outbox.rb +23 -23
  325. data/lib/hecks/runtime/policy_interpreter.rb +54 -54
  326. data/lib/hecks/runtime/port_operation_interpreter.rb +22 -19
  327. data/lib/hecks/runtime/query_interpreter.rb +55 -64
  328. data/lib/hecks/runtime/reaction_invocation.rb +20 -20
  329. data/lib/hecks/runtime/read_model_interpreter.rb +40 -40
  330. data/lib/hecks/runtime/rebuild_sweep.rb +4 -4
  331. data/lib/hecks/runtime/reference_hop.rb +6 -6
  332. data/lib/hecks/runtime/refusal_wording.rb +92 -115
  333. data/lib/hecks/runtime/registry/saga_persistence.rb +21 -21
  334. data/lib/hecks/runtime/registry/verification.rb +36 -26
  335. data/lib/hecks/runtime/registry.rb +45 -28
  336. data/lib/hecks/runtime/remote_dispatcher.rb +38 -23
  337. data/lib/hecks/runtime/routing.rb +10 -153
  338. data/lib/hecks/runtime/saga_interpreter/correlation.rb +17 -17
  339. data/lib/hecks/runtime/saga_interpreter.rb +64 -64
  340. data/lib/hecks/runtime/saga_pending_dispatch.rb +12 -12
  341. data/lib/hecks/runtime/tenant_check.rb +9 -9
  342. data/lib/hecks/runtime/tenant_scope.rb +5 -5
  343. data/lib/hecks/runtime/value/admission.rb +75 -30
  344. data/lib/hecks/runtime/value/coercion.rb +318 -127
  345. data/lib/hecks/runtime/value/entity_list_coercion.rb +34 -34
  346. data/lib/hecks/runtime/value.rb +21 -21
  347. data/lib/hecks/runtime.rb +7 -7
  348. data/lib/hecks/storehouse.rb +64 -64
  349. data/lib/hecks/version.rb +3 -3
  350. data/lib/hecks/vocabulary.rb +205 -4
  351. data/lib/hecks.rb +13 -11
  352. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +11 -11
  353. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +14 -12
  354. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +11 -11
  355. metadata +22 -2
data/lib/hecks/ir.rb CHANGED
@@ -1,19 +1,19 @@
1
1
  module Hecks
2
- # WHAT A CONSTRUCT EMITS, DECLARED RATHER THAN WRITTEN OUT.
2
+ # What a construct emits, declared rather than written out.
3
3
  #
4
- # `IR` is a thing this framework PRODUCES, not a thing its model IS.
4
+ # `IR` is a thing this framework produces, not a thing its model is.
5
5
  # The language self-hosts, and its own bluebook declares aggregates
6
6
  # named `Bluebook`, `Aggregate`, `Command`, `Entity`, `ValueObject`,
7
7
  # `Policy`, `ReadModel` — there is no `IR` aggregate anywhere in the
8
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
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
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.
12
+ # the emission, which only makes sense if the two are different things.
13
13
  #
14
- # So emitting IR is a CAPABILITY a construct has, and this is that
14
+ # So emitting IR is a capability a construct has, and this is that
15
15
  # capability: `include Hecks::IR` and declare the shape once.
16
- # The model it emits FROM is `Hecks::Bluebook` — a chapter class
16
+ # The model it emits from is `Hecks::Bluebook` — a chapter class
17
17
  # nesting everything a chapter declares. It is deliberately not named
18
18
  # after this, its own output.
19
19
  #
@@ -36,18 +36,18 @@ module Hecks
36
36
  # canonical_form: -> { CanonicalForm.table } # anything else
37
37
  # )
38
38
  #
39
- # KEY ORDER IS THE DECLARATION ORDER, and that is load-bearing rather
39
+ # Key order is the declaration order, and that is load-bearing rather
40
40
  # than cosmetic: `spec/golden/ir/*.json` pins the emitted form exactly,
41
41
  # so a reordered declaration is a changed artifact and the golden specs
42
42
  # will say so.
43
43
  module IR
44
- # THE TWO SHAPES A CONSTRUCT COMES IN, and why this module has two
44
+ # The two shapes a construct comes in, and why this module has two
45
45
  # doors instead of hiding the difference.
46
46
  #
47
47
  # `Bluebook`/`Aggregate`/`Policy`/`ReadModel` are ordinary objects —
48
48
  # metadata records, one instance per declaration. `Command`/`Entity`/
49
- # `ValueObject` are anonymous CLASSES (`Class.new(self)`, see
50
- # `Command.declare`), because those three are referenced as TYPES in
49
+ # `ValueObject` are anonymous classes (`Class.new(self)`, see
50
+ # `Command.declare`), because those three are referenced as types in
51
51
  # a bluebook (`attribute :price, Money`) and a type has to be a real
52
52
  # Ruby constant to be named.
53
53
  #
@@ -87,7 +87,7 @@ module Hecks
87
87
  def one(source) = One.new(source)
88
88
 
89
89
  # Walks the superclass chain so a `Class.new(ValueObject)` — which
90
- # is what every declared value object actually IS — inherits the
90
+ # is what every declared value object actually is — inherits the
91
91
  # shape its base declared, rather than each anonymous subclass
92
92
  # having to redeclare it.
93
93
  def ir_spec
@@ -112,7 +112,7 @@ module Hecks
112
112
  private
113
113
 
114
114
  # An instance reads its class's declaration; a class-shaped
115
- # construct IS the declaration holder.
115
+ # construct is the declaration holder.
116
116
  def ir_spec_for(construct)
117
117
  return construct.ir_spec if construct.respond_to?(:ir_spec)
118
118
 
@@ -73,6 +73,26 @@ Hecks.bluebook "Bluebook", version: "1" do
73
73
  # chapters attach to nothing, and ABSENT IS NOT EMPTY, the same
74
74
  # reading `version`/`formerly_known_as` above give.
75
75
  attribute :attaches_to, list_of(AttachesToContext)
76
+ # A CAPABILITY THIS CHAPTER ANSWERS FOR OTHER DOMAINS — declared, so
77
+ # nothing downstream has to recognise the chapter BY NAME. One row
78
+ # per (capability, key, verb): `provides "authorization", grant:
79
+ # "RoleAssignment.Assign"` is the row (authorization, grant,
80
+ # RoleAssignment.Assign). The runtime's role check, boot's
81
+ # ungoverned-role refusal, the authorization adapter and the fuzzer
82
+ # all read the rows rather than the literal "Governance". Most
83
+ # chapters provide nothing, and ABSENT IS NOT EMPTY, the same reading
84
+ # `attaches_to` above gives.
85
+ attribute :provides, list_of(Provision)
86
+
87
+ value_object "Provision" do
88
+ attribute :capability, String
89
+ attribute :key, String
90
+ attribute :verb, String
91
+ end
92
+
93
+ value_object "ProvisionText" do
94
+ attribute :value, String
95
+ end
76
96
 
77
97
  value_object "RuleText" do
78
98
  # deliberately permissive : source_token and replacement are legitimately
@@ -159,6 +179,22 @@ Hecks.bluebook "Bluebook", version: "1" do
159
179
  emits ChapterAttached
160
180
  end
161
181
 
182
+ # ONE ROW OF ONE CAPABILITY — `provides "authorization", assignments:
183
+ # ..., grant: ..., transitions: ...` offers three, one per key, in the
184
+ # order they were written.
185
+ command "Provide" do
186
+ role "Language"
187
+ goal "Declare one verb this chapter answers a capability with"
188
+
189
+ attribute :capability, ProvisionText
190
+ attribute :key, ProvisionText
191
+ attribute :verb, ProvisionText
192
+
193
+ sets :provides, append: { capability: :capability, key: :key, verb: :verb }
194
+
195
+ emits CapabilityProvided
196
+ end
197
+
162
198
  # THE WAY BACK.
163
199
  #
164
200
  # Until these existed the meta-domain was write-only: twelve categories, 34
@@ -214,6 +250,7 @@ Hecks.bluebook "Bluebook", version: "1" do
214
250
  member word: "vision", context: "Bluebook", body: "none", inner: "", opens: "", fills: "vision"
215
251
  member word: "formerly_known_as", context: "Bluebook", body: "none", inner: "", opens: "", fills: "formerly_known_as"
216
252
  member word: "attaches_to", context: "Bluebook", body: "none", inner: "", opens: "", fills: "attaches_to", calls: "attaches_to_impl"
253
+ member word: "provides", context: "Bluebook", body: "none", inner: "", opens: "", fills: "provides", calls: "provides_impl"
217
254
  member word: "core", context: "Bluebook", body: "none", inner: "", opens: "", fills: "classification"
218
255
  member word: "supporting", context: "Bluebook", body: "none", inner: "", opens: "", fills: "classification"
219
256
  member word: "generic", context: "Bluebook", body: "none", inner: "", opens: "", fills: "classification"
@@ -246,6 +283,10 @@ Hecks.bluebook "Bluebook", version: "1" do
246
283
  member keyword: "vision", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "vision", coerce: "false"
247
284
  member keyword: "formerly_known_as", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "formerly_known_as"
248
285
  member keyword: "attaches_to", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "attaches_to", variadic: "true"
286
+ member keyword: "provides", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "provides"
287
+ member keyword: "provides", context: "Bluebook", at: "", named: "assignments", kind: "text", required: "false", fills: "provides"
288
+ member keyword: "provides", context: "Bluebook", at: "", named: "grant", kind: "text", required: "false", fills: "provides"
289
+ member keyword: "provides", context: "Bluebook", at: "", named: "transitions", kind: "text", required: "false", fills: "provides"
249
290
  member keyword: "aggregate", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "name"
250
291
  member keyword: "read_model", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "name"
251
292
  member keyword: "policy", context: "Bluebook", at: "1", named: "", kind: "text", required: "true", fills: "name"
@@ -21,6 +21,13 @@ Hecks.bluebook "Bluebook" do
21
21
  attribute :on_event, PolicyText
22
22
  attribute :trigger_command, PolicyText
23
23
  attribute :target_domain, PolicyText
24
+ # AN `across` TARGET THIS DOMAIN EXPECTS NEVER TO REACH — declared on
25
+ # the policy that owns the expectation, not held in a core allowlist
26
+ # keyed by domain name. `ModelCheck` honours it both ways: the
27
+ # unknown-target and unacknowledged-relationship findings it would
28
+ # otherwise raise are expected, and a declaration whose target turns
29
+ # out to be known or acknowledged after all is STALE and fails.
30
+ attribute :expect_undelivered, PolicyText
24
31
  # THE GUARD, CARRIED AS TEXT — same discipline `Command.givens`
25
32
  # already holds: the block that wrote it is never called at
26
33
  # runtime, only its EXTRACTED SOURCE is (Ports::Extraction), so
@@ -92,6 +99,7 @@ Hecks.bluebook "Bluebook" do
92
99
  attribute :on_event, PolicyText
93
100
  attribute :trigger_command, PolicyText
94
101
  attribute :target_domain, PolicyText, optional: true
102
+ attribute :expect_undelivered, PolicyText, optional: true
95
103
  attribute :where, PolicyText, optional: true
96
104
  attribute :for_each, PolicyText, optional: true
97
105
 
@@ -102,6 +110,7 @@ Hecks.bluebook "Bluebook" do
102
110
  sets :on_event
103
111
  sets :trigger_command
104
112
  sets :target_domain
113
+ sets :expect_undelivered
105
114
  sets :where
106
115
  sets :for_each
107
116
  sets :position
@@ -153,7 +162,7 @@ Hecks.bluebook "Bluebook" do
153
162
 
154
163
  member word: "on", context: "Policy", body: "none", inner: "", opens: "", fills: "on_event", calls: "on_impl"
155
164
  member word: "trigger", context: "Policy", body: "none", inner: "", opens: "", fills: "trigger_command", calls: "trigger_impl"
156
- member word: "across", context: "Policy", body: "none", inner: "", opens: "", fills: "target_domain"
165
+ member word: "across", context: "Policy", body: "none", inner: "", opens: "", fills: "target_domain", calls: "across_impl"
157
166
  member word: "where", context: "Policy", body: "source", inner: "", opens: "", fills: "where"
158
167
  member word: "for_each", context: "Policy", body: "none", inner: "", opens: "", fills: "for_each"
159
168
 
@@ -181,6 +190,7 @@ Hecks.bluebook "Bluebook" do
181
190
  member keyword: "trigger", context: "Policy", at: "1", named: "", kind: "constant", required: "true", fills: "trigger_command"
182
191
  member keyword: "trigger", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "trigger_command"
183
192
  member keyword: "across", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "target_domain"
193
+ member keyword: "across", context: "Policy", at: "", named: "expect_undelivered", kind: "flag", required: "false", fills: "expect_undelivered"
184
194
  member keyword: "for_each", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "for_each"
185
195
  member keyword: "trigger", context: "Policy", at: "", named: "with", kind: "pairs", required: "false", fills: "with_spec", pairs_shape: "verbatim"
186
196
 
@@ -2,8 +2,11 @@ Hecks.bluebook "Bluebook" do
2
2
  aggregate "Vocabulary" do
3
3
  # These are DECLARATIONS, not runtime state — a language's admitted sets are
4
4
  # fixed when the language is defined, which is what one_of means. They carry
5
- # no commands on purpose : nothing dispatches a vocabulary, the conformance
6
- # check READS them from the IR and holds the runtime's hand-typed tables to them.
5
+ # no commands on purpose : nothing dispatches a vocabulary. They are READ
6
+ # from the IR and projected bin/project_vocabulary writes the Ruby tables
7
+ # (lib/hecks/vocabulary.rb) the runtime's constants read, and
8
+ # bin/project_rust_vocabulary writes rust/src/kernel/vocab/ — so the
9
+ # runtimes carry no hand-typed copies to drift.
7
10
  #
8
11
  # Every one of these is a set the runtime must agree with, and every one has
9
12
  # already drifted or leaked at least once :
@@ -171,9 +174,17 @@ Hecks.bluebook "Bluebook" do
171
174
  # fires for a creating command, advance_lifecycle only when a transition
172
175
  # applies — so this is the order a command that does both follows,
173
176
  # confirmed by tracing a real dispatch, not read off the source.
177
+ #
178
+ # decode_arguments leads both dispatch orders: turning the caller's raw
179
+ # facts into a command's declared arguments, before any argument gate
180
+ # judges them. A no-op in Ruby today (routing already hands the
181
+ # interpreter a decoded hash) and in the Rust kernel's dispatch loop
182
+ # (generated `from_json` still decodes and gates in one pass) — declared
183
+ # now so the Rust kernel's step enum has a place for a generated decoder
184
+ # to move into, rather than the order being implied by generated code.
174
185
  value_object "AggregateDispatchOrder" do
175
186
  attribute :step, String,
176
- one_of: ["refuse_unknown_arguments", "refuse_absent_arguments", "normalize_args",
187
+ one_of: ["decode_arguments", "refuse_unknown_arguments", "refuse_absent_arguments", "normalize_args",
177
188
  "refuse_role_mismatch", "resolve_references", "hydrate", "enforce_givens",
178
189
  "admissible_transition", "assign_creation_attributes", "apply_mutations",
179
190
  "advance_lifecycle", "delegate_to_entity", "enforce_ensures", "enforce_invariants",
@@ -197,7 +208,7 @@ Hecks.bluebook "Bluebook" do
197
208
  # both interpreters), even though nothing in the real corpus does yet.
198
209
  value_object "EntityDispatchOrder" do
199
210
  attribute :step, String,
200
- one_of: ["refuse_unknown_arguments", "refuse_absent_arguments", "normalize_args",
211
+ one_of: ["decode_arguments", "refuse_unknown_arguments", "refuse_absent_arguments", "normalize_args",
201
212
  "refuse_role_mismatch", "resolve_references", "hydrate_parent",
202
213
  "locate_element", "enforce_givens", "admissible_transition", "apply_mutations",
203
214
  "advance_lifecycle", "enforce_ensures", "enforce_invariants", "save", "emit"]
@@ -219,11 +230,10 @@ Hecks.bluebook "Bluebook" do
219
230
  # declared them. Everything here is different in kind: a LANGUAGE-LEVEL
220
231
  # refusal, the same wording for every domain, not authored per-bluebook —
221
232
  # closer to Comparison/SignTest beside it than to a given. So it follows
222
- # THEIR pattern, not given's: declared here for a human to read and a
223
- # conformance spec to hold equal, and a hand-typed table
224
- # (RefusalWording) is what a dispatch
225
- # actually reads the same reason Evaluator::SIGN_TEST_OPERATORS is
226
- # hand-typed rather than read live off this very chapter at every call.
233
+ # THEIR pattern, not given's: declared here, and projected into the
234
+ # generated tables a dispatch actually reads (Runtime::RefusalWording in
235
+ # Ruby, kernel::vocab::RefusalSite in Rust) rather than read live off
236
+ # this very chapter at every call.
227
237
  #
228
238
  # `{name}` markers are placeholders — plain text substitution, not
229
239
  # expression syntax ; a template is read, never evaluated. Two call
@@ -351,6 +361,303 @@ Hecks.bluebook "Bluebook" do
351
361
  "or read {reference}.{remote_field} directly if this rule cannot wait"
352
362
  end
353
363
 
364
+ # THE ARGUMENTS EACH RefusalTemplate TAKES, AND HOW EACH ONE IS WRITTEN.
365
+ # A template says WHERE a value goes; this says WHICH values a site
366
+ # takes (in the order its placeholders first appear) and how each is
367
+ # rendered before it goes there — so a caller hands over the raw value
368
+ # (a list of names, a name) rather than a string it formatted itself.
369
+ # BUG#134 was exactly the hand-formatted kind: Ruby's `declared_reading`
370
+ # fell back to "none" for an empty list, the Rust generators joined
371
+ # the list themselves and never did.
372
+ #
373
+ # Read by Runtime::RefusalWording.render_site (a missing or extra
374
+ # argument refuses to render at all) and projected into
375
+ # rust/src/kernel/vocab/refusal_template.rs as one typed args struct
376
+ # per site (`render_args` — a missing argument does not compile).
377
+ #
378
+ # shape — "scalar" (one value) or "list" (a collection of them)
379
+ # quoting — "none" (the value's own text) or "inspect" (Ruby's
380
+ # `#inspect`; Rust's `{:?}`), per value or per item
381
+ # separator — what a list's items are joined with
382
+ # sorted — "true" sorts a list's items first (before quoting)
383
+ # when_empty — what an empty list renders as
384
+ #
385
+ # Recorded from what the Ruby call sites did when this table was
386
+ # introduced; no wording changed. A value whose rendering depends on
387
+ # its runtime type (`Rendering.describe`, `offered.inspect` of an
388
+ # arbitrary value) stays a caller-rendered "none" scalar, as do the
389
+ # identity readings (`identity`, `heads`, `wants`) the Rust side already
390
+ # joins once at codegen time or inside `extract_wants`.
391
+ value_object "RefusalSiteArgument" do
392
+ attribute :refusal, String, admits: "Vocabulary::DomainRefusal"
393
+ attribute :site, String
394
+ attribute :argument, String
395
+ attribute :shape, String
396
+ attribute :quoting, String
397
+ attribute :separator, String
398
+ attribute :sorted, String
399
+ attribute :when_empty, String
400
+
401
+ member refusal: "NotFound", site: "creating_no_identity", argument: "command",
402
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
403
+ member refusal: "NotFound", site: "creating_no_identity", argument: "aggregate",
404
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
405
+ member refusal: "NotFound", site: "creating_no_identity", argument: "identity",
406
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
407
+ member refusal: "AlreadyExists", site: "creating_duplicate", argument: "command",
408
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
409
+ member refusal: "AlreadyExists", site: "creating_duplicate", argument: "aggregate",
410
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
411
+ member refusal: "AlreadyExists", site: "creating_duplicate", argument: "identity",
412
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
413
+ member refusal: "AlreadyExists", site: "creating_duplicate", argument: "offered",
414
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
415
+ member refusal: "AlreadyExists", site: "entity_duplicate", argument: "entity",
416
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
417
+ member refusal: "AlreadyExists", site: "entity_duplicate", argument: "aggregate",
418
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
419
+ member refusal: "AlreadyExists", site: "entity_duplicate", argument: "identity",
420
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
421
+ # One described value per identity head (MutationApplier), or the
422
+ # one offered element identity (EntityListCoercion).
423
+ member refusal: "AlreadyExists", site: "entity_duplicate", argument: "offered",
424
+ shape: "list", quoting: "none", separator: ", ", sorted: "false", when_empty: ""
425
+ member refusal: "NotFound", site: "acting_no_identity", argument: "command",
426
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
427
+ member refusal: "NotFound", site: "acting_no_identity", argument: "aggregate",
428
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
429
+ member refusal: "NotFound", site: "acting_no_identity", argument: "identity",
430
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
431
+ member refusal: "NotFound", site: "record_missing", argument: "aggregate",
432
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
433
+ member refusal: "NotFound", site: "record_missing", argument: "identity",
434
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
435
+ member refusal: "NotFound", site: "record_missing", argument: "offered",
436
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
437
+ member refusal: "NotFound", site: "entity_parent_no_identity", argument: "command",
438
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
439
+ member refusal: "NotFound", site: "entity_parent_no_identity", argument: "aggregate",
440
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
441
+ member refusal: "NotFound", site: "entity_parent_no_identity", argument: "entity",
442
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
443
+ member refusal: "NotFound", site: "entity_parent_no_identity", argument: "identity",
444
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
445
+ member refusal: "UnknownVerb", site: "entity_unknown", argument: "aggregate",
446
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
447
+ member refusal: "UnknownVerb", site: "entity_unknown", argument: "entity",
448
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
449
+ member refusal: "NotFound", site: "entity_element_no_identity", argument: "command",
450
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
451
+ member refusal: "NotFound", site: "entity_element_no_identity", argument: "entity",
452
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
453
+ member refusal: "NotFound", site: "entity_element_no_identity", argument: "identity",
454
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
455
+ member refusal: "NotFound", site: "entity_element_missing", argument: "entity",
456
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
457
+ member refusal: "NotFound", site: "entity_element_missing", argument: "identity",
458
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
459
+ member refusal: "NotFound", site: "entity_element_missing", argument: "wants",
460
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
461
+ member refusal: "NotFound", site: "entity_element_missing", argument: "aggregate",
462
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
463
+ member refusal: "NotFound", site: "entity_element_missing", argument: "parent_id",
464
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
465
+ member refusal: "NotFound", site: "reference_target_missing", argument: "target",
466
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
467
+ member refusal: "NotFound", site: "reference_target_missing", argument: "heads",
468
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
469
+ member refusal: "NotFound", site: "reference_target_missing", argument: "key",
470
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
471
+ member refusal: "NotFound", site: "read_model_reference_missing", argument: "aggregate",
472
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
473
+ member refusal: "NotFound", site: "read_model_reference_missing", argument: "offered",
474
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
475
+ member refusal: "TypeMismatch", site: "read_model_object_reference", argument: "query",
476
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
477
+ member refusal: "TypeMismatch", site: "read_model_object_reference", argument: "field",
478
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
479
+ member refusal: "UnknownVerb", site: "no_query", argument: "aggregate",
480
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
481
+ member refusal: "UnknownVerb", site: "no_query", argument: "query",
482
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
483
+ member refusal: "UnknownVerb", site: "entity_query_missing", argument: "entity",
484
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
485
+ member refusal: "UnknownVerb", site: "entity_query_missing", argument: "query",
486
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
487
+ member refusal: "UnknownVerb", site: "entity_holds_no_list", argument: "aggregate",
488
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
489
+ member refusal: "UnknownVerb", site: "entity_holds_no_list", argument: "entity",
490
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
491
+ member refusal: "UnknownVerb", site: "entity_no_command", argument: "entity",
492
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
493
+ member refusal: "UnknownVerb", site: "entity_no_command", argument: "command",
494
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
495
+ member refusal: "UnknownVerb", site: "aggregate_no_command", argument: "aggregate",
496
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
497
+ member refusal: "UnknownVerb", site: "aggregate_no_command", argument: "command",
498
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
499
+ member refusal: "UnknownVerb", site: "port_no_operation", argument: "port",
500
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
501
+ member refusal: "UnknownVerb", site: "port_no_operation", argument: "operation",
502
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
503
+ member refusal: "UnknownVerb", site: "no_domain", argument: "domain",
504
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
505
+ member refusal: "UnknownVerb", site: "no_domain", argument: "verb",
506
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
507
+ member refusal: "UnknownVerb", site: "no_read_model", argument: "domain",
508
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
509
+ member refusal: "UnknownVerb", site: "no_read_model", argument: "query",
510
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
511
+ member refusal: "UnknownVerb", site: "not_fully_qualified", argument: "verb",
512
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
513
+ member refusal: "UnknownVerb", site: "no_aggregate", argument: "domain",
514
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
515
+ member refusal: "UnknownVerb", site: "no_aggregate", argument: "aggregate",
516
+ shape: "scalar", quoting: "inspect", separator: "", sorted: "false", when_empty: ""
517
+ member refusal: "LifecycleRefused", site: "transition_blocked", argument: "command",
518
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
519
+ member refusal: "LifecycleRefused", site: "transition_blocked", argument: "field",
520
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
521
+ member refusal: "LifecycleRefused", site: "transition_blocked", argument: "current",
522
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
523
+ member refusal: "LifecycleRefused", site: "transition_blocked", argument: "allowed",
524
+ shape: "list", quoting: "inspect", separator: " or ", sorted: "false", when_empty: ""
525
+ member refusal: "TypeMismatch", site: "value_object_shape", argument: "name",
526
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
527
+ member refusal: "TypeMismatch", site: "value_object_shape", argument: "type",
528
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
529
+ member refusal: "TypeMismatch", site: "value_object_shape", argument: "offered",
530
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
531
+ member refusal: "TypeMismatch", site: "reference_wrong_shape", argument: "command",
532
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
533
+ member refusal: "TypeMismatch", site: "reference_wrong_shape", argument: "attribute",
534
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
535
+ member refusal: "TypeMismatch", site: "reference_wrong_shape", argument: "offered",
536
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
537
+ member refusal: "TypeMismatch", site: "reference_wrong_shape", argument: "known_by",
538
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
539
+ member refusal: "TypeMismatch", site: "multi_field_scalar", argument: "type",
540
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
541
+ member refusal: "TypeMismatch", site: "composite_identity", argument: "type",
542
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
543
+ member refusal: "TypeMismatch", site: "numeric_field", argument: "type",
544
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
545
+ member refusal: "TypeMismatch", site: "numeric_field", argument: "field",
546
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
547
+ member refusal: "TypeMismatch", site: "numeric_field", argument: "expected",
548
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
549
+ member refusal: "TypeMismatch", site: "numeric_field", argument: "offered",
550
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
551
+ member refusal: "TypeMismatch", site: "non_finite_field", argument: "type",
552
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
553
+ member refusal: "TypeMismatch", site: "non_finite_field", argument: "field",
554
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
555
+ member refusal: "TypeMismatch", site: "non_finite_field", argument: "offered",
556
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
557
+ member refusal: "TypeMismatch", site: "integer_range", argument: "type",
558
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
559
+ member refusal: "TypeMismatch", site: "integer_range", argument: "field",
560
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
561
+ member refusal: "TypeMismatch", site: "integer_range", argument: "offered",
562
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
563
+ member refusal: "TypeMismatch", site: "pattern_mismatch", argument: "type",
564
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
565
+ member refusal: "TypeMismatch", site: "pattern_mismatch", argument: "field",
566
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
567
+ member refusal: "TypeMismatch", site: "pattern_mismatch", argument: "pattern",
568
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
569
+ member refusal: "TypeMismatch", site: "pattern_mismatch", argument: "offered",
570
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
571
+ member refusal: "TypeMismatch", site: "arithmetic_amount", argument: "op",
572
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
573
+ member refusal: "TypeMismatch", site: "arithmetic_amount", argument: "target",
574
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
575
+ member refusal: "TypeMismatch", site: "arithmetic_amount", argument: "offered",
576
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
577
+ member refusal: "TypeMismatch", site: "arithmetic_current", argument: "op",
578
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
579
+ member refusal: "TypeMismatch", site: "arithmetic_current", argument: "target",
580
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
581
+ member refusal: "TypeMismatch", site: "arithmetic_current", argument: "offered",
582
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
583
+ member refusal: "TypeMismatch", site: "arithmetic_shared_field", argument: "op",
584
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
585
+ member refusal: "TypeMismatch", site: "arithmetic_shared_field", argument: "target",
586
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
587
+ member refusal: "UnknownArgument", site: "unknown_args", argument: "command",
588
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
589
+ member refusal: "UnknownArgument", site: "unknown_args", argument: "unknown",
590
+ shape: "list", quoting: "none", separator: ", ", sorted: "true", when_empty: ""
591
+ member refusal: "UnknownArgument", site: "unknown_args", argument: "declared",
592
+ shape: "list", quoting: "none", separator: ", ", sorted: "false", when_empty: "none"
593
+ member refusal: "AbsentArgument", site: "absent_args", argument: "command",
594
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
595
+ member refusal: "AbsentArgument", site: "absent_args", argument: "absent",
596
+ shape: "list", quoting: "none", separator: ", ", sorted: "true", when_empty: ""
597
+ member refusal: "AbsentArgument", site: "absent_args", argument: "declared",
598
+ shape: "list", quoting: "none", separator: ", ", sorted: "false", when_empty: "none"
599
+ member refusal: "InvariantViolation", site: "closed_set_member", argument: "type",
600
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
601
+ member refusal: "InvariantViolation", site: "closed_set_member", argument: "admitted",
602
+ shape: "list", quoting: "inspect", separator: ", ", sorted: "false", when_empty: ""
603
+ member refusal: "InvariantViolation", site: "closed_set_member", argument: "offered",
604
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
605
+ member refusal: "InvariantViolation", site: "value_object_invariant", argument: "name",
606
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
607
+ member refusal: "InvariantViolation", site: "value_object_invariant", argument: "description",
608
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
609
+ member refusal: "InvariantViolation", site: "value_object_invariant", argument: "offered",
610
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
611
+ member refusal: "InvariantViolation", site: "admits_declared_set", argument: "name",
612
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
613
+ member refusal: "InvariantViolation", site: "admits_declared_set", argument: "admits",
614
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
615
+ member refusal: "InvariantViolation", site: "admits_declared_set", argument: "admitted",
616
+ shape: "list", quoting: "inspect", separator: ", ", sorted: "false", when_empty: ""
617
+ member refusal: "InvariantViolation", site: "admits_declared_set", argument: "offered",
618
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
619
+ member refusal: "InvariantViolation", site: "undeclared_set", argument: "name",
620
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
621
+ member refusal: "InvariantViolation", site: "undeclared_set", argument: "admits",
622
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
623
+ member refusal: "Unauthorized", site: "tenant_required", argument: "query",
624
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
625
+ member refusal: "Unauthorized", site: "tenant_required", argument: "field",
626
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
627
+ member refusal: "Unauthorized", site: "role_mismatch", argument: "command",
628
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
629
+ member refusal: "Unauthorized", site: "role_mismatch", argument: "role",
630
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
631
+ member refusal: "Unauthorized", site: "role_mismatch", argument: "caller_role",
632
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
633
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "aggregate",
634
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
635
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "field",
636
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
637
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "tenant",
638
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
639
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "attribute",
640
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
641
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "target",
642
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
643
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "target_field",
644
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
645
+ member refusal: "Unauthorized", site: "cross_tenant_reference", argument: "other",
646
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
647
+ member refusal: "AttributeAbsent", site: "absent_read", argument: "aggregate",
648
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
649
+ member refusal: "AttributeAbsent", site: "absent_read", argument: "field",
650
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
651
+ member refusal: "ProjectionAbsent", site: "absent_read", argument: "aggregate",
652
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
653
+ member refusal: "ProjectionAbsent", site: "absent_read", argument: "field",
654
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
655
+ member refusal: "ProjectionAbsent", site: "absent_read", argument: "reference",
656
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
657
+ member refusal: "ProjectionAbsent", site: "absent_read", argument: "remote_field",
658
+ shape: "scalar", quoting: "none", separator: "", sorted: "false", when_empty: ""
659
+ end
660
+
354
661
  # SagaInterpreter::REFUSED.
355
662
  #
356
663
  # A leg answers an EVENT — `on "AccountDebited"` — or it answers one of these,
@@ -373,10 +680,9 @@ Hecks.bluebook "Bluebook" do
373
680
  # rendering convention, the same guess for every domain, not
374
681
  # authored per-bluebook — closer to Comparison/SignTest than to a
375
682
  # given. `pattern` is the regex SOURCE, no delimiters or flags
376
- # (Ruby's own `Regexp#source`) — spec/field_hint_conformance_spec.rb
377
- # holds FieldShape's four hand-typed constants equal to this, both
378
- # directions, the same conformance shape refusal_wording_
379
- # conformance_spec.rb already holds RefusalTemplate to.
683
+ # (Ruby's own `Regexp#source`) — FieldShape builds its four constants
684
+ # off these rows, and bin/project_field_hints writes the Rust host's
685
+ # copy from them, so neither side is typed by hand.
380
686
  #
381
687
  # `resolves_to` names WHICH Field attribute a match sets — `html_type`
382
688
  # for email/url/tel (three candidates, only one wins, checked in that
@@ -392,5 +698,34 @@ Hecks.bluebook "Bluebook" do
392
698
  member name: "tel", pattern: 'phone|\btel(ephone)?\b', resolves_to: "html_type"
393
699
  member name: "textarea", pattern: '\b(text|body|note|notes|description|message|comment)\b', resolves_to: "kind"
394
700
  end
701
+
702
+ # The Rust keywords (strict + reserved) a generated identifier must not
703
+ # collide with — RustProjection::Projector::RUST_KEYWORDS (rust/project/
704
+ # naming.rb) reads this, and bin/project_reserved_names projects it into
705
+ # rust/codegen/src/reserved_names.rs, so the Ruby and Rust generators
706
+ # escape (a field: `r#type`) or refuse (a module name) the SAME words.
707
+ # Declared once here because the two hand-typed copies were held equal
708
+ # by nothing but a comment.
709
+ value_object "RustReservedWord" do
710
+ attribute :word, String,
711
+ one_of: ["as", "break", "const", "continue", "crate", "dyn", "else", "enum", "extern", "false",
712
+ "fn", "for", "if", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub",
713
+ "ref", "return", "self", "Self", "static", "struct", "super", "trait", "true", "type",
714
+ "unsafe", "use", "where", "while", "abstract", "become", "box", "do", "final", "macro",
715
+ "override", "priv", "typeof", "unsized", "virtual", "yield", "try"]
716
+ end
717
+
718
+ # The keys a domain's own name must not take, because that name doubles
719
+ # as a Cargo `[features]` key: every key rust/Cargo.toml already uses
720
+ # outside `[features]` (`[package]`, `[lib]`, `[[bin]]`) plus `default`,
721
+ # which Cargo reserves for the auto-enabled feature set. Read by
722
+ # RustProjection::Projector::CARGO_RESERVED_DOMAIN_NAMES and projected by
723
+ # bin/project_reserved_names, same as RustReservedWord above.
724
+ value_object "CargoReservedName" do
725
+ attribute :name, String,
726
+ one_of: ["name", "version", "edition", "path", "authors", "license", "description", "default",
727
+ "features", "package", "lib", "bin", "dependencies", "dev-dependencies",
728
+ "build-dependencies", "workspace"]
729
+ end
395
730
  end
396
731
  end