hecks 0.3.0 → 1.0.1

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 (202) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hecks/adapters/driven/d1.rb +38 -14
  3. data/lib/hecks/adapters/driven/governance_authorization.rb +41 -2
  4. data/lib/hecks/adapters/driven/heki/journal.rb +7 -2
  5. data/lib/hecks/adapters/driven/heki/saga_store.rb +0 -0
  6. data/lib/hecks/adapters/driven/heki/snapshot.rb +31 -4
  7. data/lib/hecks/adapters/driven/heki.rb +40 -9
  8. data/lib/hecks/adapters/driven/lambda.rb +16 -2
  9. data/lib/hecks/adapters/driven/postgres/codec.rb +8 -0
  10. data/lib/hecks/adapters/driven/postgres/schema_builder.rb +45 -6
  11. data/lib/hecks/adapters/driven/postgres.rb +76 -29
  12. data/lib/hecks/adapters/driven/postgres_era.adapter +11 -0
  13. data/lib/hecks/adapters/driven/sql_query_builder.rb +1 -1
  14. data/lib/hecks/adapters/driven/sqlite/codec.rb +17 -0
  15. data/lib/hecks/adapters/driven/sqlite/projection.rb +76 -9
  16. data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +17 -5
  17. data/lib/hecks/adapters/driven/sqlite.rb +30 -9
  18. data/lib/hecks/adapters/driven.rb +19 -1
  19. data/lib/hecks/behaviors/dsl.rb +29 -0
  20. data/lib/hecks/behaviors/expectations.rb +62 -2
  21. data/lib/hecks/bluebook/assembly/contracts.rb +36 -7
  22. data/lib/hecks/bluebook/assembly/marks.rb +4 -3
  23. data/lib/hecks/bluebook/assembly.rb +14 -1
  24. data/lib/hecks/bluebook/behaviour/lifecycle.rb +18 -1
  25. data/lib/hecks/bluebook/behaviour/process_manager.rb +14 -1
  26. data/lib/hecks/bluebook/behaviour/value_object.rb +13 -7
  27. data/lib/hecks/bluebook/chapter.rb +21 -11
  28. data/lib/hecks/bluebook/command.rb +1 -1
  29. data/lib/hecks/bluebook/dsl/aggregate_builder.rb +117 -5
  30. data/lib/hecks/bluebook/dsl/attribute_collector.rb +21 -0
  31. data/lib/hecks/bluebook/dsl/bluebook_builder.rb +71 -2
  32. data/lib/hecks/bluebook/dsl/command_builder.rb +144 -3
  33. data/lib/hecks/bluebook/dsl/domain_port_builder.rb +49 -7
  34. data/lib/hecks/bluebook/dsl/entity_builder.rb +129 -4
  35. data/lib/hecks/bluebook/dsl/policy_builder.rb +18 -3
  36. data/lib/hecks/bluebook/dsl/port_builder.rb +12 -3
  37. data/lib/hecks/bluebook/dsl/process_manager_builder.rb +109 -10
  38. data/lib/hecks/bluebook/dsl/rule_reference.rb +1 -0
  39. data/lib/hecks/bluebook/dsl/word_gate.rb +9 -2
  40. data/lib/hecks/bluebook/dsl/world_builder.rb +44 -4
  41. data/lib/hecks/bluebook/expression/ast_json.rb +149 -0
  42. data/lib/hecks/bluebook/expression/canonical_form.rb +71 -3
  43. data/lib/hecks/bluebook/expression/evaluator.rb +50 -7
  44. data/lib/hecks/bluebook/expression/projection.json +48 -0
  45. data/lib/hecks/bluebook/expression/resolver.rb +161 -10
  46. data/lib/hecks/bluebook/expression.rb +1 -0
  47. data/lib/hecks/bluebook/hexagon.rb +1 -1
  48. data/lib/hecks/bluebook/meta_validator/judge.rb +78 -16
  49. data/lib/hecks/bluebook/meta_validator/port_judge.rb +4 -0
  50. data/lib/hecks/bluebook/meta_validator/readings.rb +14 -4
  51. data/lib/hecks/bluebook/meta_validator/reconstruction.rb +42 -3
  52. data/lib/hecks/bluebook/meta_validator/shapes.rb +30 -10
  53. data/lib/hecks/bluebook/meta_validator.rb +103 -13
  54. data/lib/hecks/bluebook/model_check.rb +147 -6
  55. data/lib/hecks/bluebook/pattern_subset.rb +66 -2
  56. data/lib/hecks/bluebook/process_manager.rb +53 -11
  57. data/lib/hecks/bluebook/project_register.rb +25 -0
  58. data/lib/hecks/bluebook/value_object.rb +19 -2
  59. data/lib/hecks/doc/reference.rb +22 -1
  60. data/lib/hecks/facade/cli_door.rb +6 -3
  61. data/lib/hecks/facade/json_door.rb +16 -4
  62. data/lib/hecks/forms/app.rb +47 -6
  63. data/lib/hecks/forms/command_form_renderer.rb +1 -1
  64. data/lib/hecks/forms/field_renderer.rb +11 -4
  65. data/lib/hecks/forms/html.rb +31 -0
  66. data/lib/hecks/forms/params.rb +30 -1
  67. data/lib/hecks/forms/port_argument.rb +46 -0
  68. data/lib/hecks/forms/record_renderer.rb +6 -2
  69. data/lib/hecks/forms/record_table.rb +6 -1
  70. data/lib/hecks/framework/bluebook/console_settings.bluebook +19 -19
  71. data/lib/hecks/framework/bluebook/governance.bluebook +26 -11
  72. data/lib/hecks/framework/bluebook/identity.bluebook +2 -2
  73. data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +527 -0
  74. data/lib/hecks/fuzzing/invalid_value_generator.rb +3 -2
  75. data/lib/hecks/fuzzing/isolated_boot.rb +212 -18
  76. data/lib/hecks/fuzzing/properties.rb +52 -6
  77. data/lib/hecks/fuzzing/replay.rb +51 -18
  78. data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +28 -2
  79. data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +71 -6
  80. data/lib/hecks/fuzzing/sequence_generator.rb +5 -4
  81. data/lib/hecks/fuzzing/value_generator.rb +25 -2
  82. data/lib/hecks/grammar/evolve.rb +33 -0
  83. data/lib/hecks/grammar/expression.bluebook +8 -5
  84. data/lib/hecks/grammar/expression_operators.json +497 -1
  85. data/lib/hecks/language/bluebook/aggregate.bluebook +12 -12
  86. data/lib/hecks/language/bluebook/bluebook.bluebook +3 -3
  87. data/lib/hecks/language/bluebook/command.bluebook +42 -8
  88. data/lib/hecks/language/bluebook/entity.bluebook +86 -10
  89. data/lib/hecks/language/bluebook/policy.bluebook +21 -4
  90. data/lib/hecks/language/bluebook/process_manager.bluebook +135 -18
  91. data/lib/hecks/language/bluebook/projection.bluebook +6 -6
  92. data/lib/hecks/language/bluebook/query.bluebook +4 -4
  93. data/lib/hecks/language/bluebook/shape.bluebook +6 -6
  94. data/lib/hecks/language/bluebook/syntax.bluebook +12 -11
  95. data/lib/hecks/language/bluebook/vocabulary.bluebook +22 -7
  96. data/lib/hecks/language/hecksagon/domain_port.bluebook +25 -1
  97. data/lib/hecks/language/oidc.json +20 -0
  98. data/lib/hecks/language/port.bluebook +30 -2
  99. data/lib/hecks/naming.rb +54 -1
  100. data/lib/hecks/ports/access_control.port +7 -2
  101. data/lib/hecks/ports/access_control.rb +1 -1
  102. data/lib/hecks/ports/agent.port +6 -2
  103. data/lib/hecks/ports/agent.rb +1 -1
  104. data/lib/hecks/ports/authentication.port +4 -2
  105. data/lib/hecks/ports/authentication.rb +1 -1
  106. data/lib/hecks/ports/authorization.port +5 -2
  107. data/lib/hecks/ports/authorization.rb +14 -11
  108. data/lib/hecks/ports/clock.port +3 -2
  109. data/lib/hecks/ports/clock.rb +1 -1
  110. data/lib/hecks/ports/extraction.port +3 -2
  111. data/lib/hecks/ports/extraction.rb +1 -1
  112. data/lib/hecks/ports/identity_assignment.port +3 -2
  113. data/lib/hecks/ports/identity_assignment.rb +1 -1
  114. data/lib/hecks/ports/identity_generation.port +3 -2
  115. data/lib/hecks/ports/identity_generation.rb +1 -1
  116. data/lib/hecks/ports/identity_resolution.port +3 -2
  117. data/lib/hecks/ports/identity_resolution.rb +1 -1
  118. data/lib/hecks/ports/persistence/append_only.rb +40 -4
  119. data/lib/hecks/ports/persistence/execution.rb +6 -1
  120. data/lib/hecks/ports/persistence/plugin.rb +54 -0
  121. data/lib/hecks/{runtime → ports/persistence/plugins/era}/era_check.rb +41 -8
  122. data/lib/hecks/{runtime → ports/persistence/plugins/era}/era_guard.rb +24 -56
  123. data/lib/hecks/ports/persistence/{lineage.rb → plugins/era/lineage.rb} +31 -4
  124. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/era_store.rb +3 -3
  125. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/head_compiler.rb +59 -10
  126. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/mint_transaction.rb +2 -2
  127. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/provisioning.rb +29 -1
  128. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/tail_merge.rb +11 -4
  129. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/transform_installer.rb +20 -0
  130. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage.rb +1 -1
  131. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage_manager/coverage_check.rb +5 -5
  132. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage_manager/era_resolver.rb +5 -2
  133. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage_manager/merge_coordinator.rb +2 -2
  134. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage_manager/minter.rb +4 -4
  135. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage_manager.rb +2 -2
  136. data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era.rb +116 -29
  137. data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/audit/approval_digest.rb +1 -1
  138. data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/audit/layer_one.rb +14 -5
  139. data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/audit/layer_two.rb +31 -6
  140. data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/audit/unfed_report.rb +5 -1
  141. data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/reattest.rb +3 -3
  142. data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/scaffold/differ.rb +1 -1
  143. data/lib/hecks/ports/persistence/plugins/era.rb +48 -0
  144. data/lib/hecks/ports/persistence.rb +1 -1
  145. data/lib/hecks/ports/projection.rb +20 -0
  146. data/lib/hecks/projections/diagrams.rb +230 -1
  147. data/lib/hecks/projections/shape.rb +15 -2
  148. data/lib/hecks/projector/cli_projector.rb +10 -1
  149. data/lib/hecks/projector/exporter.rb +19 -2
  150. data/lib/hecks/query_ir.rb +19 -0
  151. data/lib/hecks/query_specification/common/null_policy.rb +13 -1
  152. data/lib/hecks/query_specification/field_path.rb +20 -2
  153. data/lib/hecks/query_specification/hop_path.rb +7 -5
  154. data/lib/hecks/runtime/aggregate_lock.rb +45 -0
  155. data/lib/hecks/runtime/boot_gates.rb +41 -0
  156. data/lib/hecks/runtime/caller.rb +19 -3
  157. data/lib/hecks/runtime/command_interpreter/argument_gate.rb +13 -2
  158. data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +12 -0
  159. data/lib/hecks/runtime/command_interpreter.rb +165 -34
  160. data/lib/hecks/runtime/command_rules/admissibility.rb +101 -16
  161. data/lib/hecks/runtime/command_rules/arithmetic.rb +40 -4
  162. data/lib/hecks/runtime/command_rules/authorization.rb +2 -1
  163. data/lib/hecks/runtime/command_rules/references.rb +27 -19
  164. data/lib/hecks/runtime/dependency_planning.rb +66 -5
  165. data/lib/hecks/runtime/dispatcher.rb +19 -4
  166. data/lib/hecks/runtime/entity_interpreter.rb +92 -14
  167. data/lib/hecks/runtime/errors.rb +22 -0
  168. data/lib/hecks/runtime/identity.rb +30 -2
  169. data/lib/hecks/runtime/instance.rb +59 -4
  170. data/lib/hecks/runtime/interpreting.rb +21 -0
  171. data/lib/hecks/runtime/loader.rb +59 -18
  172. data/lib/hecks/runtime/query_interpreter.rb +36 -4
  173. data/lib/hecks/runtime/reaction_invocation.rb +9 -1
  174. data/lib/hecks/runtime/read_model_interpreter.rb +89 -5
  175. data/lib/hecks/runtime/refusal_wording.rb +2 -0
  176. data/lib/hecks/runtime/registry/saga_persistence.rb +75 -3
  177. data/lib/hecks/runtime/registry/verification.rb +88 -0
  178. data/lib/hecks/runtime/registry.rb +69 -8
  179. data/lib/hecks/runtime/saga_interpreter.rb +215 -13
  180. data/lib/hecks/runtime/saga_pending_dispatch.rb +45 -0
  181. data/lib/hecks/runtime/value/admission.rb +19 -1
  182. data/lib/hecks/runtime/value/coercion.rb +75 -10
  183. data/lib/hecks/runtime.rb +17 -5
  184. data/lib/hecks/storehouse.rb +632 -0
  185. data/lib/hecks/version.rb +1 -1
  186. data/lib/hecks/vocabulary.rb +6 -1
  187. data/lib/hecks.rb +28 -3
  188. data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +90 -0
  189. data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +128 -0
  190. data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +160 -0
  191. metadata +49 -37
  192. /data/lib/hecks/{runtime → ports/persistence/plugins/era}/era_guard/shape_diff.rb +0 -0
  193. /data/lib/hecks/{runtime → ports/persistence/plugins/era}/era_tamper.rb +0 -0
  194. /data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/field_cache.rb +0 -0
  195. /data/lib/hecks/{adapters/driven → ports/persistence/plugins/era}/postgres_era/lineage/resumable_backfill.rb +0 -0
  196. /data/lib/hecks/{runtime → ports/persistence/plugins/era}/storage_shape.rb +0 -0
  197. /data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/audit.rb +0 -0
  198. /data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/rule_compiler.rb +0 -0
  199. /data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/scaffold/renderer.rb +0 -0
  200. /data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/scaffold/writer.rb +0 -0
  201. /data/lib/hecks/{translation → ports/persistence/plugins/era/translation}/scaffold.rb +0 -0
  202. /data/lib/hecks/{translation.rb → ports/persistence/plugins/era/translation.rb} +0 -0
@@ -54,6 +54,28 @@ Hecks.bluebook "Bluebook" do
54
54
  attribute :value, String
55
55
  end
56
56
 
57
+ # ONE DISPATCH'S OWN ORDER AMONG ITS HANDLER'S SIBLINGS — named
58
+ # DispatchPosition rather than reusing ProcessManager's own `Position`
59
+ # four lines below (same discipline as `MemberPosition`/shape.bluebook's
60
+ # own comment on the identical choice): that one orders process
61
+ # managers among a CHAPTER's siblings ; this one orders dispatches
62
+ # within ONE handler. Same shape, different fact.
63
+ #
64
+ # Part of `identified_by`, below, alongside `command_name` — a real
65
+ # handler fans the SAME command out more than once with different
66
+ # `with:` bindings each leg (item #151's own real example: one
67
+ # BodyPulse handler dispatching Signal.FireSignal once per organ),
68
+ # and `command_name` alone collided the instant it did: the Judge's
69
+ # own `entity_duplicate` check raised the moment a second dispatch of
70
+ # the same command was declared, an uncaught crash for a legitimate,
71
+ # common pattern. `position` names WHICH send this is and is safe to
72
+ # fold into identity exactly where it would not be for Handler's own
73
+ # `from_state` (a real business value) — a Dispatch is declared once,
74
+ # at load time, and never re-addressed by identity afterward.
75
+ value_object "DispatchPosition" do
76
+ attribute :value, Integer
77
+ end
78
+
57
79
  # The way back: everything DECLARED IN the chapter above. The parent
58
80
  # reference IS the query.
59
81
  # WHERE IT SITS AMONG ITS SIBLINGS. Declaration order is a FACT ABOUT THE
@@ -96,7 +118,7 @@ Hecks.bluebook "Bluebook" do
96
118
  sets :starts_on
97
119
  sets :ends_on
98
120
  sets :position
99
- emits "SagaDeclared"
121
+ emits SagaDeclared
100
122
  end
101
123
 
102
124
  command "State" do
@@ -107,7 +129,7 @@ Hecks.bluebook "Bluebook" do
107
129
 
108
130
  sets :states, append: { name: :name }
109
131
 
110
- emits "SagaStateAttached"
132
+ emits SagaStateAttached
111
133
  end
112
134
 
113
135
  # THE HANDLER'S OWN CREATION. S17, ADR 0026 — Handler is a genuine
@@ -136,7 +158,7 @@ Hecks.bluebook "Bluebook" do
136
158
 
137
159
  sets :handlers, append: { event_type: :event_type, from_state: :from_state, to_state: :to_state }
138
160
 
139
- emits "LegDeclared"
161
+ emits LegDeclared
140
162
  end
141
163
 
142
164
  # S17, ADR 0026 — ONE HANDLER, nested rather than its own root
@@ -147,22 +169,34 @@ Hecks.bluebook "Bluebook" do
147
169
  # wrong thing, holds nothing, and duplicates the reference beside it.
148
170
  #
149
171
  # `event_type` is an event name, or one of the Trigger vocabulary's
150
- # members when the leg answers something no aggregate announces — and
151
- # is Handler's own real, non-positional identity now : a saga answers
152
- # each event ONCE, so the event names the leg, and the process
153
- # manager it belongs to is structural (which list this element sits
154
- # in), not a stored field any more.
172
+ # members when the leg answers something no aggregate announces — but
173
+ # NOT, alone, Handler's own identity any more (items #151/#152's own
174
+ # finding): a state machine legitimately answers the SAME event
175
+ # differently depending on which state it is currently in one event
176
+ # name, several distinct legs (a BodyPulse handler that moves
177
+ # `attentive -> attentive` and, separately, `sleeping_light ->
178
+ # sleeping_light`) — and `event_type` alone collided the instant a
179
+ # real corpus declared that shape: the Judge's own `entity_duplicate`
180
+ # check raised `AlreadyExists` the moment the second leg was declared,
181
+ # an uncaught crash, not a refusal, for a common, legitimate pattern.
182
+ # `from_state` joins it below for exactly this reason — a real
183
+ # business value, not a stand-in for missing meaning, the same
184
+ # distinction `DispatchPosition`'s own comment (above) draws for its
185
+ # sibling `Dispatch`. The process manager this leg belongs to stays
186
+ # structural (which list this element sits in), never a stored field.
155
187
  entity "Handler" do
156
188
  description "One handler inside a process manager — the event it answers, the state move it makes, and the commands it sends. Nested under the process manager because a handler holds nested dispatches, which hold nested bindings."
157
189
 
158
- identified_by HandlerText, as: :event_type
159
-
190
+ attribute :event_type, HandlerText
160
191
  attribute :from_state, HandlerText
161
192
  attribute :to_state, HandlerText
162
193
  # S17, ADR 0026 — Dispatch nested here too (see `entity "Dispatch"`,
163
194
  # below), one level further in than Handler itself.
164
195
  attribute :dispatches, list_of(Dispatch)
165
196
 
197
+ # BOTH FIELDS TOGETHER — see the class-level comment above.
198
+ identified_by :event_type, :from_state
199
+
166
200
  # THE DISPATCH'S OWN CREATION — same reason Handler's own creation
167
201
  # lives on ProcessManager, one level up: an entity is never created
168
202
  # through its own dotted verb. Reached as a DOTTED verb itself
@@ -174,10 +208,17 @@ Hecks.bluebook "Bluebook" do
174
208
  goal "Open a dispatch inside a handler"
175
209
 
176
210
  attribute :command_name, DispatchText
211
+ # THE WALK INDEX, never author-supplied — the same generic
212
+ # POSITION handling `ValueObject.Member`'s own creating command
213
+ # already relies on (`Judge#appends`), which fills this from
214
+ # where the walk found the dispatch, not from a field the row
215
+ # happens to hold. No real `.bluebook` author ever calls this
216
+ # verb directly; only the Judge's own replay does.
217
+ attribute :position, DispatchPosition
177
218
 
178
- sets :dispatches, append: { command_name: :command_name }
219
+ sets :dispatches, append: { command_name: :command_name, position: :position }
179
220
 
180
- emits "SendDeclared"
221
+ emits SendDeclared
181
222
  end
182
223
 
183
224
  # S17, ADR 0026 — ONE COMMAND A HANDLER DISPATCHES, nested two
@@ -185,12 +226,21 @@ Hecks.bluebook "Bluebook" do
185
226
  # its Handler" (the ADR's own words). The bindings are an open
186
227
  # map, which no value object can hold — that was always a reason
187
228
  # it could not be one, never a reason it could not be an entity.
188
- # `command_name` is Dispatch's own real, non-positional identity,
189
- # the same shape Handler's own `event_type` just took one level up.
229
+ # `command_name` ALONE used to be Dispatch's own identity, the same
230
+ # shape Handler's own `event_type` took one level up — and collided
231
+ # the same way, for the same real reason (item #151): one handler
232
+ # fanning the SAME command out several times with different `with:`
233
+ # bindings each time (one BodyPulse handler dispatching
234
+ # Signal.FireSignal once per organ). `position` joins it below —
235
+ # see `DispatchPosition`'s own comment for why that field, unlike
236
+ # Handler's `from_state`, is safe to fold into identity.
190
237
  entity "Dispatch" do
191
238
  description "One command a handler dispatches, with the arguments it binds. Nested under the handler because the bindings are an open map, which no value object can hold."
192
239
 
193
- identified_by DispatchText, as: :command_name
240
+ attribute :command_name, DispatchText
241
+ attribute :position, DispatchPosition
242
+
243
+ identified_by :command_name, :position
194
244
 
195
245
  attribute :with_spec, list_of(Binding)
196
246
 
@@ -203,7 +253,50 @@ Hecks.bluebook "Bluebook" do
203
253
 
204
254
  sets :with_spec, append: { key: :key, value: :value }
205
255
 
206
- emits "BindingAttached"
256
+ emits BindingAttached
257
+ end
258
+
259
+ # THE COMPENSATING DISPATCH THIS ONE COMPENSATES FOR, IF ANY —
260
+ # FLAT FIELDS on THIS SAME entity, mirroring `command_name`/
261
+ # `with_spec` above one-for-one, rather than a nested (or
262
+ # self-referential) second `Dispatch`: an entity's own attribute
263
+ # type has to resolve against a value object, and neither a
264
+ # self-reference to `Dispatch` (written from inside its own
265
+ # block, before it exists to reference) nor a plain nested
266
+ # entity reference passes that check the way `Handler.
267
+ # dispatches: list_of(Dispatch)` does — that one resolves a
268
+ # SIBLING already fully built by the time deferred construction
269
+ # (ADR 0028) finishes; a dispatch compensating for itself has no
270
+ # such sibling. `compensates_command_name` absent means no
271
+ # compensation; present, together with whatever
272
+ # `compensates_with_spec` holds, is everything
273
+ # `Reconstruction#dispatch` needs to assemble the SAME
274
+ # `DispatchSpec` shape `compensates` (the real, author-facing
275
+ # word) fills.
276
+ attribute :compensates_command_name, DispatchText, optional: true
277
+ attribute :compensates_with_spec, list_of(Binding)
278
+
279
+ command "Compensates" do
280
+ role "Language"
281
+ goal "Name the command this dispatch compensates for"
282
+
283
+ attribute :compensates_command_name, DispatchText
284
+
285
+ sets :compensates_command_name
286
+
287
+ emits "CompensationDeclared"
288
+ end
289
+
290
+ command "BindCompensation" do
291
+ role "Language"
292
+ goal "Bind one argument of the compensation's own dispatched command"
293
+
294
+ attribute :key, DispatchText
295
+ attribute :value, DispatchText
296
+
297
+ sets :compensates_with_spec, append: { key: :key, value: :value }
298
+
299
+ emits "CompensationBindingAttached"
207
300
  end
208
301
  end
209
302
  end
@@ -224,11 +317,30 @@ Hecks.bluebook "Bluebook" do
224
317
  attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
225
318
 
226
319
  member word: "correlates_by", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "correlates_by"
227
- member word: "starts_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "starts_on"
228
- member word: "ends_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "ends_on"
320
+ # BARE CONSTANT ACCEPTED (ADR 0025, S6 — "events first-class"),
321
+ # `starts_on Transfer::TransferRequested` / `ends_on
322
+ # Transfer::TransferSettled`, same `kind: "constant"` + `kind:
323
+ # "text"` ArgumentSeed pair `emits`/policy's own `on` already
324
+ # carry (this row's own comment there). Now `calls:`-routed
325
+ # (`starts_on_impl`/`ends_on_impl`, hand-written — GenericDispatch's
326
+ # own `COERCE_BY_KIND` has no "constant" entry, so a bare
327
+ # constant needs the same `Naming.event_ref` resolution `on_impl`/
328
+ # `transition_impl` already do, not the plain `.to_s` a single
329
+ # `kind: "text"` row used to get for free).
330
+ member word: "starts_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "starts_on_impl"
331
+ member word: "ends_on", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "ends_on_impl"
229
332
  member word: "transition", context: "ProcessManager", body: "keywords", inner: "Handler", opens: "Handler", fills: "", calls: "transition_impl"
230
333
  member word: "transition", context: "ProcessManager", body: "none", inner: "", opens: "", fills: "", calls: "transition_impl"
334
+ # TWO ROWS, the SAME PAIR SHAPE `transition` takes just above —
335
+ # `body: "none"` was already the only row (`opens: "Dispatch"`
336
+ # already anticipated a block, unused until now); `body:
337
+ # "keywords"` is the new one, opening `compensates` on the
338
+ # dispatch it sits inside (per-dispatch saga compensation — see
339
+ # `ProcessManagerBuilder::HandlerBuilder#dispatch_impl`'s own
340
+ # comment).
341
+ member word: "dispatch", context: "Handler", body: "keywords", inner: "Dispatch", opens: "Dispatch", fills: "", calls: "dispatch_impl"
231
342
  member word: "dispatch", context: "Handler", body: "none", inner: "", opens: "Dispatch", fills: "", calls: "dispatch_impl"
343
+ member word: "compensates", context: "Dispatch", body: "none", inner: "", opens: "", fills: "", calls: "compensates_impl"
232
344
 
233
345
  end
234
346
 
@@ -250,7 +362,9 @@ Hecks.bluebook "Bluebook" do
250
362
  attribute :blank_message, String
251
363
 
252
364
  member keyword: "correlates_by", context: "ProcessManager", at: "1", named: "", kind: "symbol", required: "true", fills: "correlates_by"
365
+ member keyword: "starts_on", context: "ProcessManager", at: "1", named: "", kind: "constant", required: "true", fills: "starts_on"
253
366
  member keyword: "starts_on", context: "ProcessManager", at: "1", named: "", kind: "text", required: "true", fills: "starts_on"
367
+ member keyword: "ends_on", context: "ProcessManager", at: "1", named: "", kind: "constant", required: "true", fills: "ends_on"
254
368
  member keyword: "ends_on", context: "ProcessManager", at: "1", named: "", kind: "text", required: "true", fills: "ends_on"
255
369
  member keyword: "transition", context: "ProcessManager", at: "1", named: "", kind: "pairs", required: "true", fills: "", pair_key_fills: "event_type", pair_value_fills: "to_state", pairs_shape: "fields"
256
370
  member keyword: "transition", context: "ProcessManager", at: "", named: "from", kind: "text", required: "true", fills: "from_state"
@@ -258,6 +372,9 @@ Hecks.bluebook "Bluebook" do
258
372
  member keyword: "dispatch", context: "Handler", at: "1", named: "", kind: "constant", required: "true", fills: "command_name"
259
373
  member keyword: "dispatch", context: "Handler", at: "1", named: "", kind: "text", required: "true", fills: "command_name"
260
374
  member keyword: "dispatch", context: "Handler", at: "", named: "with", kind: "pairs", required: "false", fills: "with_spec", pairs_shape: "verbatim"
375
+ member keyword: "compensates", context: "Dispatch", at: "1", named: "", kind: "constant", required: "true", fills: "command_name"
376
+ member keyword: "compensates", context: "Dispatch", at: "1", named: "", kind: "text", required: "true", fills: "command_name"
377
+ member keyword: "compensates", context: "Dispatch", at: "", named: "with", kind: "pairs", required: "false", fills: "with_spec", pairs_shape: "verbatim"
261
378
 
262
379
  end
263
380
  end
@@ -110,7 +110,7 @@ Hecks.bluebook "Bluebook" do
110
110
  sets :reference_name
111
111
  sets :reference_target
112
112
  sets :position
113
- emits "ProjectionDeclared"
113
+ emits ProjectionDeclared
114
114
  end
115
115
 
116
116
  command "Gather" do
@@ -140,7 +140,7 @@ Hecks.bluebook "Bluebook" do
140
140
 
141
141
  sets :aggregate_heads, append: { aggregate: :aggregate, as: :as, many: :many }
142
142
 
143
- emits "HeadGathered"
143
+ emits HeadGathered
144
144
  end
145
145
 
146
146
  command "GroupBy" do
@@ -153,7 +153,7 @@ Hecks.bluebook "Bluebook" do
153
153
 
154
154
  sets :group_by, append: { field: :field }
155
155
 
156
- emits "GroupByFieldAdded"
156
+ emits GroupByFieldAdded
157
157
  end
158
158
 
159
159
  # `count`/`median` are LATE-SET scalars, the same shape `Lifecycle`'s
@@ -171,7 +171,7 @@ Hecks.bluebook "Bluebook" do
171
171
 
172
172
  sets :count
173
173
 
174
- emits "CountDeclared"
174
+ emits CountDeclared
175
175
  end
176
176
 
177
177
  command "Median" do
@@ -183,7 +183,7 @@ Hecks.bluebook "Bluebook" do
183
183
 
184
184
  sets :median_field
185
185
 
186
- emits "MedianFieldSet"
186
+ emits MedianFieldSet
187
187
  end
188
188
 
189
189
  command "Option" do
@@ -200,7 +200,7 @@ Hecks.bluebook "Bluebook" do
200
200
 
201
201
  sets :options, append: { option: :option, key: :key, value: :value, at: :at }
202
202
 
203
- emits "OptionAttached"
203
+ emits OptionAttached
204
204
  end
205
205
 
206
206
  # HOW READMODEL IS SPELLED. These rows live with the concept
@@ -118,7 +118,7 @@ Hecks.bluebook "Bluebook" do
118
118
  sets :order_way
119
119
  sets :limit
120
120
  sets :position
121
- emits "AskDeclared"
121
+ emits AskDeclared
122
122
  end
123
123
 
124
124
  command "Filter" do
@@ -132,7 +132,7 @@ Hecks.bluebook "Bluebook" do
132
132
 
133
133
  sets :wheres, append: { field: :field, op: :op, value: :value }
134
134
 
135
- emits "FilterAttached"
135
+ emits FilterAttached
136
136
  end
137
137
 
138
138
  command "Option" do
@@ -153,7 +153,7 @@ Hecks.bluebook "Bluebook" do
153
153
 
154
154
  sets :options, append: { option: :option, key: :key, value: :value, at: :at }
155
155
 
156
- emits "OptionAttached"
156
+ emits OptionAttached
157
157
  end
158
158
 
159
159
  command "Argument" do
@@ -176,7 +176,7 @@ Hecks.bluebook "Bluebook" do
176
176
 
177
177
  sets :attributes, append: { name: :name, type: :type, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
178
178
 
179
- emits "AskArgumentAttached"
179
+ emits AskArgumentAttached
180
180
  end
181
181
 
182
182
 
@@ -109,7 +109,7 @@ Hecks.bluebook "Bluebook" do
109
109
  sets :aggregate
110
110
  sets :name
111
111
  sets :position
112
- emits "ShapeDeclared"
112
+ emits ShapeDeclared
113
113
  end
114
114
 
115
115
  command "Field" do
@@ -134,7 +134,7 @@ Hecks.bluebook "Bluebook" do
134
134
 
135
135
  sets :attributes, append: { name: :name, type: :type, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
136
136
 
137
- emits "ShapeFieldAttached"
137
+ emits ShapeFieldAttached
138
138
  end
139
139
 
140
140
  command "Close" do
@@ -150,7 +150,7 @@ Hecks.bluebook "Bluebook" do
150
150
 
151
151
  sets :rows
152
152
 
153
- emits "ShapeClosed"
153
+ emits ShapeClosed
154
154
  end
155
155
 
156
156
  command "Assert" do
@@ -165,7 +165,7 @@ Hecks.bluebook "Bluebook" do
165
165
 
166
166
  sets :invariants, append: { description: :description, canonical: :canonical }
167
167
 
168
- emits "AssertionAttached"
168
+ emits AssertionAttached
169
169
  end
170
170
 
171
171
  value_object "ValueObjectText" do
@@ -192,7 +192,7 @@ Hecks.bluebook "Bluebook" do
192
192
 
193
193
  sets :members, append: { position: :position }
194
194
 
195
- emits "MemberDeclared"
195
+ emits MemberDeclared
196
196
  end
197
197
 
198
198
  # S17, ADR 0026 — ONE ADMITTED ROW, nested rather than its own root
@@ -228,7 +228,7 @@ Hecks.bluebook "Bluebook" do
228
228
 
229
229
  sets :pairs, append: { key: :key, value: :value }
230
230
 
231
- emits "PairBound"
231
+ emits PairBound
232
232
  end
233
233
  end
234
234
 
@@ -86,8 +86,8 @@ Hecks.bluebook "Bluebook" do
86
86
  value_object "Context" do
87
87
  attribute :name, String,
88
88
  one_of: ["File", "Bluebook", "Aggregate", "Entity", "Command", "Query", "ValueObject", "OneOf",
89
- "Lifecycle", "Policy", "ProcessManager", "Handler", "ReadModel", "Type", "Hecksagon",
90
- "World", "DomainPort", "PortOperation", "Port", "Adapter", "Translation",
89
+ "Lifecycle", "Policy", "ProcessManager", "Handler", "Dispatch", "ReadModel", "Type",
90
+ "Hecksagon", "World", "DomainPort", "PortOperation", "Port", "Adapter", "Translation",
91
91
  "TranslationAggregate"]
92
92
  end
93
93
 
@@ -252,8 +252,9 @@ Hecks.bluebook "Bluebook" do
252
252
  # WHICH DISAMBIGUATOR keyword argument a bare reference may supply
253
253
  # when `resolves_via` is `owner_keyed` — see `Disambiguator`'s own
254
254
  # comment. BLANK unless `resolves_via` is `owner_keyed` AND more
255
- # than one candidate can register (today: only `given` on
256
- # Aggregate).
255
+ # than one candidate can register (today: `given` on Aggregate,
256
+ # and `given` on Entity, one level down — chapter-wide sharing at
257
+ # each scope it has grown to).
257
258
  attribute :disambiguator, KeywordSeedText, admits: "Syntax::Disambiguator", optional: true
258
259
  # THE ESCAPE HATCH — item #13's full metaprogrammed dispatch (slice
259
260
  # 3, whole-project table-unification survey). BLANK for every word
@@ -291,14 +292,14 @@ Hecks.bluebook "Bluebook" do
291
292
  role "Language"
292
293
  goal "Mark a word as on its way out, still read"
293
294
 
294
- emits "KeywordDeprecated"
295
+ emits KeywordDeprecated
295
296
  end
296
297
 
297
298
  command "Retire" do
298
299
  role "Language"
299
300
  goal "Remove a word from every generated parser table"
300
301
 
301
- emits "KeywordRetired"
302
+ emits KeywordRetired
302
303
  end
303
304
  end
304
305
 
@@ -375,14 +376,14 @@ Hecks.bluebook "Bluebook" do
375
376
  role "Language"
376
377
  goal "Mark an argument as on its way out, still read"
377
378
 
378
- emits "ArgumentDeprecated"
379
+ emits ArgumentDeprecated
379
380
  end
380
381
 
381
382
  command "Retire" do
382
383
  role "Language"
383
384
  goal "Remove an argument from every generated parser table"
384
385
 
385
- emits "ArgumentRetired"
386
+ emits ArgumentRetired
386
387
  end
387
388
  end
388
389
 
@@ -408,7 +409,7 @@ Hecks.bluebook "Bluebook" do
408
409
  sets :bluebook
409
410
  sets :name
410
411
 
411
- emits "SyntaxDeclared"
412
+ emits SyntaxDeclared
412
413
  end
413
414
 
414
415
  # THE KEYWORD'S OWN CREATION. An entity is never created through its
@@ -426,7 +427,7 @@ Hecks.bluebook "Bluebook" do
426
427
  inner: :inner, opens: :opens, fills: :fills, was: :was,
427
428
  resolves_via: :resolves_via, disambiguator: :disambiguator, calls: :calls }
428
429
 
429
- emits "KeywordAdmitted"
430
+ emits KeywordAdmitted
430
431
  end
431
432
 
432
433
  command "Argument" do
@@ -441,7 +442,7 @@ Hecks.bluebook "Bluebook" do
441
442
  variadic: :variadic, minimum: :minimum,
442
443
  coerce: :coerce, blank_message: :blank_message }
443
444
 
444
- emits "ArgumentAdmitted"
445
+ emits ArgumentAdmitted
445
446
  end
446
447
  end
447
448
  end
@@ -130,6 +130,13 @@ Hecks.bluebook "Bluebook" do
130
130
  # shape append does (`with: {...}` is a field map, same as
131
131
  # append's own `fields:`), so it carries no sign, same reading.
132
132
  member name: "delegate", sign: ""
133
+ # CommandBuilder#corrects_impl's own comment gives the full
134
+ # reasoning — a command declaring a past event it amends, rather
135
+ # than a fresh mutation of its own. Rides the SAME multi-binding
136
+ # wire shape append/delegate do (`as:`/`reason:`/`reverses:`,
137
+ # assembled into one `source` hash by hand, same as `with:` is),
138
+ # so it carries no sign either.
139
+ member name: "corrects", sign: ""
133
140
  end
134
141
 
135
142
  # QuerySpecification::Common::Comparators::COMPARATORS — a where-clause's
@@ -175,17 +182,23 @@ Hecks.bluebook "Bluebook" do
175
182
 
176
183
  # EntityInterpreter#call — the same shape
177
184
  # one level down, on a piece an aggregate holds rather than the aggregate
178
- # itself. Shorter than AggregateDispatchOrder because an entity is never
179
- # CREATED through this path (no assign_creation_attributes) and inherits
180
- # its aggregate's own argument gate rather than running one of its own (no
181
- # refuse_unknown_arguments) hydrating the parent and locating the
185
+ # itself. `refuse_unknown_arguments`/`refuse_absent_arguments` lead it,
186
+ # the same position they hold in AggregateDispatchOrder — bug audit H1
187
+ # (docs/audits/2026-08-10-main-bug-audit.md): an entity command used to
188
+ # run NEITHER at all, on a since-corrected comment claiming it "inherits
189
+ # its aggregate's own gate" — nothing on this path ever ran one, and a
190
+ # bogus argument or a silently-nil'd absent one both went straight
191
+ # through. The only real difference from AggregateDispatchOrder now is
192
+ # that an entity is never CREATED through this path (no
193
+ # assign_creation_attributes) — hydrating the parent and locating the
182
194
  # element replace a single hydrate. resolve_references stayed, though —
183
195
  # an entity command can declare a reference-typed attribute the same way
184
196
  # an aggregate command can (CommandRules#resolve_references is shared by
185
197
  # both interpreters), even though nothing in the real corpus does yet.
186
198
  value_object "EntityDispatchOrder" do
187
199
  attribute :step, String,
188
- one_of: ["normalize_args", "refuse_role_mismatch", "resolve_references", "hydrate_parent",
200
+ one_of: ["refuse_unknown_arguments", "refuse_absent_arguments", "normalize_args",
201
+ "refuse_role_mismatch", "resolve_references", "hydrate_parent",
189
202
  "locate_element", "enforce_givens", "admissible_transition", "apply_mutations",
190
203
  "advance_lifecycle", "enforce_ensures", "enforce_invariants", "save", "emit"]
191
204
  end
@@ -196,8 +209,8 @@ Hecks.bluebook "Bluebook" do
196
209
  value_object "DomainRefusal" do
197
210
  attribute :name, String,
198
211
  one_of: ["AbsentArgument", "AlreadyExists", "AttributeAbsent", "EnsuresNotMet", "GivenNotMet",
199
- "InvariantViolation", "LifecycleRefused", "NotFound", "ProjectionAbsent", "RemoteRefusal",
200
- "TypeMismatch", "Unauthorized", "UnknownArgument", "UnknownVerb"]
212
+ "InvariantViolation", "LifecycleRefused", "NothingToCorrect", "NotFound", "ProjectionAbsent",
213
+ "RemoteRefusal", "TypeMismatch", "Unauthorized", "UnknownArgument", "UnknownVerb"]
201
214
  end
202
215
 
203
216
  # THE WORDING ITSELF, for every DomainRefusal site that is not already
@@ -279,6 +292,8 @@ Hecks.bluebook "Bluebook" do
279
292
  template: "{type} is a composite identity — an identity must have exactly one field"
280
293
  member refusal: "TypeMismatch", site: "numeric_field",
281
294
  template: "{type}.{field} expects {expected}, got {offered}"
295
+ member refusal: "TypeMismatch", site: "non_finite_field",
296
+ template: "{type}.{field} must be a finite number, got {offered}"
282
297
  member refusal: "TypeMismatch", site: "pattern_mismatch",
283
298
  template: "{type}.{field} must match {pattern}, got {offered}"
284
299
  member refusal: "TypeMismatch", site: "arithmetic_amount",
@@ -4,7 +4,9 @@ Hecks.bluebook "Hecksagon" do
4
4
 
5
5
  identified_by PortName, as: :name
6
6
 
7
- attribute :verb, PortVerb, optional: true
7
+ attribute :verb, PortVerb, optional: true
8
+ attribute :signal, PortSignal, optional: true
9
+ attribute :answers, list_of(PortAnswer)
8
10
 
9
11
  value_object "PortName" do
10
12
  attribute :value, String
@@ -16,6 +18,24 @@ Hecks.bluebook "Hecksagon" do
16
18
  invariant("a verb is named") { !value.to_s.empty? }
17
19
  end
18
20
 
21
+ # SAME CLOSED SET port.bluebook's own "Port" aggregate declares —
22
+ # kept as its own local value object rather than shared cross-
23
+ # chapter, the same way PortVerb already is here.
24
+ value_object "PortSignal" do
25
+ attribute :value, String, one_of: ["reply", "effect"]
26
+ end
27
+
28
+ # `answers` — DomainPortBuilder's own twin of PortBuilder#answers
29
+ # (port.bluebook's "Port" aggregate, same shape), added once a real
30
+ # `.port` file migrated to parse through this builder (the repoint
31
+ # `lib/hecks.rb#port`'s own comment describes) used the word
32
+ # (`extraction.port`'s own `answers :canonical`). Local, not shared
33
+ # cross-chapter, same reasoning as PortSignal just above.
34
+ value_object "PortAnswer" do
35
+ attribute :value, String
36
+ invariant("an answer names a real method") { !value.to_s.empty? }
37
+ end
38
+
19
39
  # HOW DOMAINPORT IS SPELLED. These rows live with the concept
20
40
  # they describe; SyntaxBoot discovers every aggregate-local seed table.
21
41
  # Contexts represented here: DomainPort.
@@ -35,6 +55,8 @@ Hecks.bluebook "Hecksagon" do
35
55
  member word: "tells", context: "DomainPort", body: "keywords", inner: "PortOperation", opens: "PortOperation", fills: "", calls: "tells_impl"
36
56
  member word: "asks", context: "DomainPort", body: "keywords", inner: "PortOperation", opens: "PortOperation", fills: "", calls: "asks_impl"
37
57
  member word: "verb", context: "DomainPort", body: "none", inner: "", opens: "", fills: "verb"
58
+ member word: "signal", context: "DomainPort", body: "none", inner: "", opens: "", fills: "signal"
59
+ member word: "answers", context: "DomainPort", body: "none", inner: "", opens: "", fills: "answers"
38
60
 
39
61
  end
40
62
 
@@ -59,6 +81,8 @@ Hecks.bluebook "Hecksagon" do
59
81
  member keyword: "tells", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "name"
60
82
  member keyword: "asks", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "name"
61
83
  member keyword: "verb", context: "DomainPort", at: "1", named: "", kind: "text", required: "true", fills: "verb"
84
+ member keyword: "signal", context: "DomainPort", at: "1", named: "", kind: "symbol", required: "true", fills: "signal"
85
+ member keyword: "answers", context: "DomainPort", at: "1", named: "", kind: "symbol", required: "true", fills: "answers"
62
86
 
63
87
  # THE RECEIVING AGGREGATE — PortOperationBuilder's own `reference_to`
64
88
  # (inside the block) is refused (#335); this is the sanctioned
@@ -126,6 +126,11 @@
126
126
  "verb": "Bluebook::Entity.Declare",
127
127
  "role": "Language"
128
128
  },
129
+ {
130
+ "scope": "bluebook:entity.holds",
131
+ "verb": "Bluebook::Entity.Holds",
132
+ "role": "Language"
133
+ },
129
134
  {
130
135
  "scope": "bluebook:entity.identify",
131
136
  "verb": "Bluebook::Entity.Identify",
@@ -146,6 +151,11 @@
146
151
  "verb": "Bluebook::Entity.Precondition",
147
152
  "role": "Language"
148
153
  },
154
+ {
155
+ "scope": "bluebook:entity.reference",
156
+ "verb": "Bluebook::Entity.Reference",
157
+ "role": "Language"
158
+ },
149
159
  {
150
160
  "scope": "bluebook:entity.seal",
151
161
  "verb": "Bluebook::Entity.Seal",
@@ -186,6 +196,16 @@
186
196
  "verb": "Bluebook::ProcessManager.Handler.Dispatch.Bind",
187
197
  "role": "Language"
188
198
  },
199
+ {
200
+ "scope": "bluebook:process_manager.handler.dispatch.bind_compensation",
201
+ "verb": "Bluebook::ProcessManager.Handler.Dispatch.BindCompensation",
202
+ "role": "Language"
203
+ },
204
+ {
205
+ "scope": "bluebook:process_manager.handler.dispatch.compensates",
206
+ "verb": "Bluebook::ProcessManager.Handler.Dispatch.Compensates",
207
+ "role": "Language"
208
+ },
189
209
  {
190
210
  "scope": "bluebook:process_manager.state",
191
211
  "verb": "Bluebook::ProcessManager.State",