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
@@ -146,7 +146,7 @@ Hecks.bluebook "Bluebook" do
146
146
  sets :description
147
147
  sets :provenance
148
148
  sets :position
149
- emits "RootDeclared"
149
+ emits RootDeclared
150
150
  end
151
151
 
152
152
  # ONE PART OF THE IDENTITY, attached the way one attribute is. It was an
@@ -182,7 +182,7 @@ Hecks.bluebook "Bluebook" do
182
182
  given("an identity part names something") { !path.value.to_s.empty? }
183
183
 
184
184
  sets :identified_by, append: { value: :path }
185
- emits "RootIdentified"
185
+ emits RootIdentified
186
186
  end
187
187
 
188
188
  # The way back, one level down: the aggregates DECLARED IN a chapter, found by
@@ -238,7 +238,7 @@ Hecks.bluebook "Bluebook" do
238
238
 
239
239
  sets :attributes, append: { name: :name, type: :type, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
240
240
 
241
- emits "AttributeAttached"
241
+ emits AttributeAttached
242
242
  end
243
243
 
244
244
  # An attribute that points at ANOTHER aggregate's head.
@@ -276,7 +276,7 @@ Hecks.bluebook "Bluebook" do
276
276
 
277
277
  sets :attributes, append: { name: :name, type: :points_at, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
278
278
 
279
- emits "ReferenceAttached"
279
+ emits ReferenceAttached
280
280
  end
281
281
 
282
282
  # An attribute whose type names a PIECE this aggregate holds.
@@ -303,7 +303,7 @@ Hecks.bluebook "Bluebook" do
303
303
 
304
304
  sets :attributes, append: { name: :name, type: :holds, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
305
305
 
306
- emits "PieceHeld"
306
+ emits PieceHeld
307
307
  end
308
308
 
309
309
  # THE ONLY RULE THAT CAN REFUSE AN UNNAMED ATTRIBUTE, and it lives here.
@@ -357,7 +357,7 @@ Hecks.bluebook "Bluebook" do
357
357
  sets :state_field
358
358
  sets :state_start
359
359
 
360
- emits "LifecycleNamed"
360
+ emits LifecycleNamed
361
361
  end
362
362
 
363
363
  command "Transition" do
@@ -370,7 +370,7 @@ Hecks.bluebook "Bluebook" do
370
370
 
371
371
  sets :transitions, append: { command: :command, from_state: :from_state, to_state: :to_state }
372
372
 
373
- emits "TransitionAttached"
373
+ emits TransitionAttached
374
374
  end
375
375
 
376
376
  command "Seal" do
@@ -410,7 +410,7 @@ Hecks.bluebook "Bluebook" do
410
410
  # is Identify's rule ; this one only asks that there be one.
411
411
  given("an aggregate says what it is known by") { !identified_by.empty? }
412
412
 
413
- emits "RootSealed"
413
+ emits RootSealed
414
414
  end
415
415
 
416
416
  command "Value" do
@@ -421,7 +421,7 @@ Hecks.bluebook "Bluebook" do
421
421
 
422
422
  sets :value_objects, append: { name: :name }
423
423
 
424
- emits "ValueDeclared"
424
+ emits ValueDeclared
425
425
  end
426
426
 
427
427
  # THE AGGREGATE BOUNDARY (S10, ADR 0025 — "Rules") — the same shape
@@ -438,7 +438,7 @@ Hecks.bluebook "Bluebook" do
438
438
 
439
439
  sets :invariants, append: { description: :description, canonical: :canonical }
440
440
 
441
- emits "InvariantAttached"
441
+ emits InvariantAttached
442
442
  end
443
443
 
444
444
  # A PRECONDITION SHARED ACROSS COMMANDS, DECLARED ONCE (S10, ADR
@@ -456,7 +456,7 @@ Hecks.bluebook "Bluebook" do
456
456
 
457
457
  sets :preconditions, append: { description: :description, canonical: :canonical }
458
458
 
459
- emits "PreconditionAttached"
459
+ emits PreconditionAttached
460
460
  end
461
461
 
462
462
  # THE LOCAL HALF OF A CROSS-AGGREGATE READ (S12, ADR 0025) — the
@@ -478,7 +478,7 @@ Hecks.bluebook "Bluebook" do
478
478
 
479
479
  sets :projected_fields, append: { name: :name, reference: :reference, remote_field: :remote_field }
480
480
 
481
- emits "ProjectedFieldAttached"
481
+ emits ProjectedFieldAttached
482
482
  end
483
483
 
484
484
  # HOW AGGREGATE IS SPELLED. These rows live with the concept
@@ -136,7 +136,7 @@ Hecks.bluebook "Bluebook", version: "1" do
136
136
  sets :version
137
137
  sets :formerly_known_as
138
138
 
139
- emits "ChapterDeclared"
139
+ emits ChapterDeclared
140
140
  end
141
141
 
142
142
  # ONE CONTEXT THE CHAPTER ATTACHES TO, appended the way one identity
@@ -156,7 +156,7 @@ Hecks.bluebook "Bluebook", version: "1" do
156
156
  # ledger entry was posted") { ledger.size == old.ledger.size + 1
157
157
  # } — one more row than before, never fewer, never the same.
158
158
  ensures("the list grew by exactly one") { attaches_to.size == old.attaches_to.size + 1 }
159
- emits "ChapterAttached"
159
+ emits ChapterAttached
160
160
  end
161
161
 
162
162
  # THE WAY BACK.
@@ -192,7 +192,7 @@ Hecks.bluebook "Bluebook", version: "1" do
192
192
  replacement: :replacement, boundary: :boundary, position: :position
193
193
  }
194
194
 
195
- emits "NormalisationAttached"
195
+ emits NormalisationAttached
196
196
  end
197
197
 
198
198
  # HOW BLUEBOOK IS SPELLED. These rows live with the concept
@@ -161,7 +161,7 @@ Hecks.bluebook "Bluebook" do
161
161
  sets :provenance
162
162
  sets :from
163
163
  sets :position
164
- emits "VerbDeclared"
164
+ emits VerbDeclared
165
165
  end
166
166
 
167
167
  command "Argument" do
@@ -190,7 +190,7 @@ Hecks.bluebook "Bluebook" do
190
190
 
191
191
  sets :attributes, append: { name: :name, type: :type, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
192
192
 
193
- emits "ArgumentAttached"
193
+ emits ArgumentAttached
194
194
  end
195
195
 
196
196
  # An argument that points at ANOTHER aggregate's head — the same word
@@ -223,7 +223,7 @@ Hecks.bluebook "Bluebook" do
223
223
 
224
224
  sets :attributes, append: { name: :name, type: :points_at, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
225
225
 
226
- emits "ArgumentReferenceAttached"
226
+ emits ArgumentReferenceAttached
227
227
  end
228
228
 
229
229
  value_object "ArgName" do
@@ -248,7 +248,7 @@ Hecks.bluebook "Bluebook" do
248
248
 
249
249
  sets :givens, append: { description: :description, canonical: :canonical }
250
250
 
251
- emits "RuleAttached"
251
+ emits RuleAttached
252
252
  end
253
253
 
254
254
  command "Ensure" do
@@ -263,7 +263,7 @@ Hecks.bluebook "Bluebook" do
263
263
 
264
264
  sets :ensures, append: { description: :description, canonical: :canonical }
265
265
 
266
- emits "EnsureAttached"
266
+ emits EnsureAttached
267
267
  end
268
268
 
269
269
  value_object "RuleText" do
@@ -289,7 +289,7 @@ Hecks.bluebook "Bluebook" do
289
289
 
290
290
  sets :mutations, append: { target: :target, op: :op, field: :field, kind: :kind, source: :source }
291
291
 
292
- emits "ChangeAttached"
292
+ emits ChangeAttached
293
293
  end
294
294
 
295
295
  value_object "FieldRef" do
@@ -319,7 +319,7 @@ Hecks.bluebook "Bluebook" do
319
319
 
320
320
  sets :references, to: :root
321
321
 
322
- emits "ReferenceNamed"
322
+ emits ReferenceNamed
323
323
  end
324
324
 
325
325
  command "Announce" do
@@ -332,7 +332,7 @@ Hecks.bluebook "Bluebook" do
332
332
 
333
333
  sets :emits, append: { name: :announces }
334
334
 
335
- emits "AnnouncementNamed"
335
+ emits AnnouncementNamed
336
336
  end
337
337
 
338
338
  # HOW COMMAND IS SPELLED. These rows live with the concept
@@ -375,6 +375,19 @@ Hecks.bluebook "Bluebook" do
375
375
  member word: "state", context: "Command", body: "none", inner: "", opens: "", fills: "mutations"
376
376
  member word: "attribute", context: "Command", body: "none", inner: "", opens: "", fills: "attributes", calls: "attribute_impl"
377
377
  member word: "ensures", context: "Command", body: "source", inner: "", opens: "", fills: "ensures"
378
+ # RETROACTIVE CORRECTION — a command that amends a specific past
379
+ # event rather than acting fresh (see this domain's own ADR on why:
380
+ # sagas only compensate their OWN anticipated failures, eras only
381
+ # reinterpret stored shape, and the event log stays append-only —
382
+ # so nothing existing lets a command say "this is amending a fact
383
+ # we already announced, and here is why"). STORED AS A MUTATION,
384
+ # not a new Command field — the same reasoning `delegates_to`'s own
385
+ # comment gives in full: `mutations:` is ALREADY a fully round-
386
+ # tripped part of the self-hosted meta-domain's own contract, and a
387
+ # genuinely new top-level Command field is not. `corrects` rides the
388
+ # SAME multi-binding wire shape `append`/`delegate` already use
389
+ # (CommandBuilder#corrects_impl's own comment has the rest).
390
+ member word: "corrects", context: "Command", body: "none", inner: "", opens: "", fills: "mutations", calls: "corrects_impl"
378
391
 
379
392
  end
380
393
 
@@ -422,6 +435,15 @@ Hecks.bluebook "Bluebook" do
422
435
  member keyword: "then_set", context: "Command", at: "", named: "remove", kind: "literal", required: "false", fills: "source", selects: "op=remove"
423
436
  member keyword: "delegates_to", context: "Command", at: "1", named: "", kind: "text", required: "true", fills: "target"
424
437
  member keyword: "delegates_to", context: "Command", at: "", named: "with", kind: "literal", required: "false", fills: "source", selects: "op=delegate"
438
+ # BARE CONSTANT ACCEPTED (ADR 0025, S6 — "events first-class"),
439
+ # `emits Account::AccountFrozen`, same `kind: "constant"` +
440
+ # `kind: "text"` pair `on`'s own row in `policy.bluebook` carries
441
+ # — both stay admitted, the old spelling not refused, for the
442
+ # same reason (event names aren't 100% corpus-migrated the way
443
+ # command references are). `CommandBuilder#emits` (hand-written,
444
+ # no `calls:` needed — the single-fill path already invokes it by
445
+ # its own word name) resolves either shape via `Naming.event_ref`.
446
+ member keyword: "emits", context: "Command", at: "1", named: "", kind: "constant", required: "true", fills: "emits"
425
447
  member keyword: "emits", context: "Command", at: "1", named: "", kind: "text", required: "true", fills: "emits"
426
448
  member keyword: "state", context: "Command", at: "1", named: "", kind: "symbol", required: "true", fills: "source"
427
449
  member keyword: "attribute", context: "Command", at: "1", named: "", kind: "symbol", required: "true", fills: "name"
@@ -431,6 +453,18 @@ Hecks.bluebook "Bluebook" do
431
453
  member keyword: "attribute", context: "Command", at: "", named: "pattern", kind: "text", required: "false", fills: "pattern"
432
454
  member keyword: "attribute", context: "Command", at: "", named: "admits", kind: "text", required: "false", fills: "admits"
433
455
  member keyword: "attribute", context: "Command", at: "", named: "one_of", kind: "list", required: "false", fills: "one_of"
456
+ # `corrects` — see the KeywordSeed row's own comment. `event` is the
457
+ # only positional and the only required-by-the-grammar argument;
458
+ # `reason` is required IN PRACTICE (CommandBuilder#corrects_impl
459
+ # refuses its absence by hand, the same way `sets` refuses two ops
460
+ # at once — a fact about runtime state, not a pure per-row fill, so
461
+ # it stays hand-enforced rather than declared `required: "true"`
462
+ # here, which would only gate the row's OWN presence, not a sibling
463
+ # kwarg's).
464
+ member keyword: "corrects", context: "Command", at: "1", named: "", kind: "text", required: "true", fills: "target"
465
+ member keyword: "corrects", context: "Command", at: "", named: "as", kind: "symbol", required: "false", fills: "source"
466
+ member keyword: "corrects", context: "Command", at: "", named: "reason", kind: "text", required: "false", fills: "source"
467
+ member keyword: "corrects", context: "Command", at: "", named: "reverses", kind: "flag", required: "false", fills: "source"
434
468
 
435
469
  end
436
470
  end
@@ -107,7 +107,7 @@ Hecks.bluebook "Bluebook" do
107
107
  sets :name
108
108
  sets :description
109
109
  sets :position
110
- emits "PieceDeclared"
110
+ emits PieceDeclared
111
111
  end
112
112
 
113
113
  # ONE PART OF THE PIECE'S IDENTITY, attached exactly as an aggregate's is.
@@ -134,7 +134,7 @@ Hecks.bluebook "Bluebook" do
134
134
  given("an identity part names something") { !path.value.to_s.empty? }
135
135
 
136
136
  sets :identified_by, append: { value: :path }
137
- emits "PieceIdentified"
137
+ emits PieceIdentified
138
138
  end
139
139
 
140
140
  command "Seal" do
@@ -146,15 +146,23 @@ Hecks.bluebook "Bluebook" do
146
146
 
147
147
  given("an entity says what it is known by") { !identified_by.empty? }
148
148
 
149
- emits "PieceSealed"
149
+ emits PieceSealed
150
150
  end
151
151
 
152
152
  command "Attribute" do
153
153
  role "Language"
154
154
  goal "Attach one attribute to the entity"
155
155
 
156
+ # THE TYPE IS A REFERENCE TO THE VALUE OBJECT IT NAMES — the same rule
157
+ # Aggregate.Attribute enforces one construct over (see that command's own
158
+ # comment). An entity declares no value objects of its own (Entity never
159
+ # answers `value_object` — entity.rb's own comment says why); its
160
+ # attributes read the SAME pool its enclosing aggregate declares, so this
161
+ # still resolves as a reference, not free text. An entity attribute naming
162
+ # an undeclared value object failed to fail: `type` rode as plain text, so
163
+ # reference resolution never ran and a typo'd or invented type boots clean.
164
+ reference_to ValueObject, as: :type
156
165
  attribute :name, EntityText
157
- attribute :type, EntityText
158
166
  attribute :list, EntityText
159
167
  attribute :optional, EntityText, optional: true
160
168
  attribute :pattern, EntityText, optional: true
@@ -164,7 +172,66 @@ Hecks.bluebook "Bluebook" do
164
172
 
165
173
  sets :attributes, append: { name: :name, type: :type, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
166
174
 
167
- emits "PieceAttributeAttached"
175
+ emits PieceAttributeAttached
176
+ end
177
+
178
+ # An attribute that points at ANOTHER AGGREGATE'S HEAD — the SAME
179
+ # construct Aggregate.Reference is, one level down (see that
180
+ # command's own comment for why the type cannot be text): `belongs_to`/
181
+ # `has_one`/`has_many`/`reference_to` are declared on an entity by the
182
+ # same DSL (`EntityBuilder`/`AttributeCollector`) an aggregate uses,
183
+ # and a real fixture already exercises it (`spec/relationship_
184
+ # declaration_spec.rb`'s "uses the same relationship declarations on
185
+ # an entity", `docs/reference/entity.md`). Without this verb such an
186
+ # attribute fell to the SAME `Attribute` verb above, which reads
187
+ # `type` as a value-object reference — so a cross-aggregate reference
188
+ # declared on a piece failed reference resolution against the wrong
189
+ # pool the moment entity attributes started being checked at all.
190
+ command "Reference" do
191
+ role "Language"
192
+ goal "Attach an attribute that points at another aggregate's head"
193
+
194
+ reference_to Aggregate, as: :points_at
195
+ attribute :name, EntityText
196
+ attribute :list, EntityText
197
+ attribute :optional, EntityText, optional: true
198
+ attribute :pattern, EntityText, optional: true
199
+ attribute :default, EntityText, optional: true
200
+ attribute :admits, EntityText, optional: true
201
+ attribute :relationship, EntityText, optional: true
202
+
203
+ sets :attributes, append: { name: :name, type: :points_at, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
204
+
205
+ emits PieceReferenceAttached
206
+ end
207
+
208
+ # An attribute whose type names a PIECE NESTED INSIDE THIS ONE — the
209
+ # SAME construct Aggregate.Holds is, one level down (see that
210
+ # command's own comment): `attribute :dispatches, list_of(Dispatch)`
211
+ # inside `entity "Handler"` (S17, ADR 0026's own two-level chain) is
212
+ # exactly `Account#ledger` one level further in. Without this verb
213
+ # such an attribute fell to the SAME `Attribute` verb above, which
214
+ # reads `type` as a value-object reference — so a piece nested inside
215
+ # a piece failed reference resolution against the wrong pool the
216
+ # moment entity attributes started being checked at all (found live:
217
+ # the meta-grammar's own `Handler.dispatches` naming `Dispatch`,
218
+ # nested inside Handler itself).
219
+ command "Holds" do
220
+ role "Language"
221
+ goal "Attach an attribute whose type is a piece nested inside this one"
222
+
223
+ reference_to Entity, as: :holds
224
+ attribute :name, EntityText
225
+ attribute :list, EntityText
226
+ attribute :optional, EntityText, optional: true
227
+ attribute :pattern, EntityText, optional: true
228
+ attribute :default, EntityText, optional: true
229
+ attribute :admits, EntityText, optional: true
230
+ attribute :relationship, EntityText, optional: true
231
+
232
+ sets :attributes, append: { name: :name, type: :holds, list: :list, default: :default, optional: :optional, pattern: :pattern, admits: :admits, relationship: :relationship }
233
+
234
+ emits PieceHeld
168
235
  end
169
236
 
170
237
 
@@ -184,7 +251,7 @@ Hecks.bluebook "Bluebook" do
184
251
 
185
252
  sets :preconditions, append: { description: :description, canonical: :canonical }
186
253
 
187
- emits "PiecePreconditionAttached"
254
+ emits PiecePreconditionAttached
188
255
  end
189
256
 
190
257
  # A PIECE'S OWN SHAPE RULE, DECLARED ONCE (round 7) — see
@@ -203,7 +270,7 @@ Hecks.bluebook "Bluebook" do
203
270
 
204
271
  sets :invariants, append: { description: :description, canonical: :canonical }
205
272
 
206
- emits "PieceInvariantAttached"
273
+ emits PieceInvariantAttached
207
274
  end
208
275
 
209
276
  command "Lifecycle" do
@@ -214,7 +281,7 @@ Hecks.bluebook "Bluebook" do
214
281
  sets :state_field
215
282
  sets :state_start
216
283
 
217
- emits "PieceLifecycleNamed"
284
+ emits PieceLifecycleNamed
218
285
  end
219
286
 
220
287
  command "Transition" do
@@ -227,7 +294,7 @@ Hecks.bluebook "Bluebook" do
227
294
 
228
295
  sets :transitions, append: { command: :command, from_state: :from_state, to_state: :to_state }
229
296
 
230
- emits "PieceTransitionAttached"
297
+ emits PieceTransitionAttached
231
298
  end
232
299
 
233
300
  # HOW ENTITY IS SPELLED. These rows live with the concept
@@ -248,7 +315,7 @@ Hecks.bluebook "Bluebook" do
248
315
  member word: "description", context: "Entity", body: "none", inner: "", opens: "", fills: "description"
249
316
  member word: "identified_by", context: "Entity", body: "keywords", inner: "ValueObject", opens: "ValueObject", fills: "identified_by", calls: "identified_by_impl"
250
317
  member word: "identified_by", context: "Entity", body: "none", inner: "", opens: "", fills: "identified_by", calls: "identified_by_impl"
251
- member word: "given", context: "Entity", body: "source", inner: "", opens: "", fills: "preconditions", calls: "given_impl"
318
+ member word: "given", context: "Entity", body: "source", inner: "", opens: "", fills: "preconditions", resolves_via: "owner_keyed", disambiguator: "declared_by", calls: "given_impl"
252
319
  member word: "invariant", context: "Entity", body: "source", inner: "", opens: "", fills: "invariants", calls: "invariant_impl"
253
320
  member word: "command", context: "Entity", body: "keywords", inner: "Command", opens: "Command", fills: "", calls: "command_impl"
254
321
  member word: "query", context: "Entity", body: "keywords", inner: "Query", opens: "Query", fills: "", calls: "query_impl"
@@ -282,6 +349,15 @@ Hecks.bluebook "Bluebook" do
282
349
 
283
350
  member keyword: "description", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "description", coerce: "false"
284
351
  member keyword: "given", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "description"
352
+ # PLAIN TEXT, not `kind: "constant"` — unlike `Aggregate`'s own
353
+ # `declared_by:` (which names a real aggregate constant), a piece
354
+ # has no first-class, independently-addressable reference anywhere
355
+ # in this language. "AggregateName.EntityName" ships as a string,
356
+ # the same way `admits:` shipped textual before its own
357
+ # constant-bridge existed — see `EntityBuilder#given_impl`'s own
358
+ # comment for why this is a deliberate, not temporary-by-oversight,
359
+ # divergence.
360
+ member keyword: "given", context: "Entity", at: "", named: "declared_by", kind: "text", required: "false", fills: "declared_by"
285
361
  member keyword: "invariant", context: "Entity", at: "1", named: "", kind: "text", required: "true", fills: "description"
286
362
  member keyword: "identified_by", context: "Entity", at: "1", named: "", kind: "symbol", required: "false", fills: "identified_by", variadic: "true", minimum: "2"
287
363
  member keyword: "identified_by", context: "Entity", at: "1", named: "", kind: "constant", required: "false", fills: "type"
@@ -105,7 +105,7 @@ Hecks.bluebook "Bluebook" do
105
105
  sets :where
106
106
  sets :for_each
107
107
  sets :position
108
- emits "ReactionDeclared"
108
+ emits ReactionDeclared
109
109
  end
110
110
 
111
111
  command "Bind" do
@@ -117,12 +117,28 @@ Hecks.bluebook "Bluebook" do
117
117
 
118
118
  sets :with_spec, append: { key: :key, value: :value }
119
119
 
120
- emits "TriggerBindingAttached"
120
+ emits TriggerBindingAttached
121
121
  end
122
122
 
123
123
  # HOW POLICY IS SPELLED. These rows live with the concept
124
124
  # they describe; SyntaxBoot discovers every aggregate-local seed table.
125
125
  # Contexts represented here: Policy.
126
+ #
127
+ # `on`'s ArgumentSeed gained a `kind: "constant"` row alongside its
128
+ # existing `kind: "text"` one (ADR 0025, S6 — "events first-class"),
129
+ # same shape `trigger`'s own pair already carries — `on
130
+ # Account::AccountFrozen`, a bare constant, now parses the same way
131
+ # `trigger Account::Debit` does. `calls: "on_impl"` routes the word
132
+ # through a hand-written method (`PolicyBuilder#on_impl`) instead of
133
+ # the generic single-fill coercion, mirroring `trigger`'s own
134
+ # `calls: "trigger_impl"` on the row below. UNLIKE `trigger`,
135
+ # `on_impl` does NOT refuse the quoted-text form outside
136
+ # `shadow_parse` — command references were safe to refuse that way
137
+ # only because they're 100% migrated across the live corpus; event
138
+ # names (`emits`/`on`) are not (only Account's `AccountFrozen` is,
139
+ # this pass), so refusing the old spelling here would break every
140
+ # live `.bluebook` site this pass didn't touch. Both forms stay
141
+ # admitted until a full corpus migration lands.
126
142
  value_object "KeywordSeed" do
127
143
  attribute :word, String
128
144
  attribute :context, String, admits: "Syntax::Context"
@@ -135,7 +151,7 @@ Hecks.bluebook "Bluebook" do
135
151
  attribute :resolves_via, String, default: "", admits: "Syntax::ResolutionScope"
136
152
  attribute :disambiguator, String, default: "", admits: "Syntax::Disambiguator"
137
153
 
138
- member word: "on", context: "Policy", body: "none", inner: "", opens: "", fills: "on_event"
154
+ member word: "on", context: "Policy", body: "none", inner: "", opens: "", fills: "on_event", calls: "on_impl"
139
155
  member word: "trigger", context: "Policy", body: "none", inner: "", opens: "", fills: "trigger_command", calls: "trigger_impl"
140
156
  member word: "across", context: "Policy", body: "none", inner: "", opens: "", fills: "target_domain"
141
157
  member word: "where", context: "Policy", body: "source", inner: "", opens: "", fills: "where"
@@ -160,7 +176,8 @@ Hecks.bluebook "Bluebook" do
160
176
  attribute :coerce, String
161
177
  attribute :blank_message, String
162
178
 
163
- member keyword: "on", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "on_event"
179
+ member keyword: "on", context: "Policy", at: "1", named: "", kind: "constant", required: "true", fills: "on_event"
180
+ member keyword: "on", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "on_event"
164
181
  member keyword: "trigger", context: "Policy", at: "1", named: "", kind: "constant", required: "true", fills: "trigger_command"
165
182
  member keyword: "trigger", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "trigger_command"
166
183
  member keyword: "across", context: "Policy", at: "1", named: "", kind: "text", required: "true", fills: "target_domain"