hecks 2.7.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +11 -0
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +18 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
- data/lib/hecks/bluebook/model_check.rb +102 -600
- data/lib/hecks/bluebook/pattern_subset.rb +11 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +84 -0
- data/lib/hecks/cli/document.rb +86 -0
- data/lib/hecks/cli/ir.rb +45 -0
- data/lib/hecks/cli/mcp.rb +31 -0
- data/lib/hecks/cli/mcp_door.rb +366 -0
- data/lib/hecks/cli/model_check.rb +203 -0
- data/lib/hecks/cli/project_cli.rb +90 -0
- data/lib/hecks/cli/project_diagrams.rb +36 -0
- data/lib/hecks/cli/run.rb +173 -0
- data/lib/hecks/cli/smoke_test.rb +45 -0
- data/lib/hecks/cli/stores.rb +53 -0
- data/lib/hecks/cli.rb +160 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +30 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +12 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_door_scope.rb +95 -0
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +62 -65
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +23 -103
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projections/bootstrap_table.rb +11 -43
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +151 -679
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +20 -582
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +9 -16
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +46 -138
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +93 -0
- data/lib/hecks/release/runner/commands.rb +66 -0
- data/lib/hecks/release/runner/console.rb +52 -0
- data/lib/hecks/release/runner/gem_publisher.rb +43 -0
- data/lib/hecks/release/runner/git.rb +48 -0
- data/lib/hecks/release/runner/npm_publisher.rb +75 -0
- data/lib/hecks/release/runner/preflight.rb +104 -0
- data/lib/hecks/release/runner/published.rb +55 -0
- data/lib/hecks/release/runner/tagger.rb +80 -0
- data/lib/hecks/release/runner.rb +215 -0
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +125 -307
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +65 -220
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +103 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +146 -567
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks/vocabulary.rb +5 -0
- data/lib/hecks.rb +32 -82
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- metadata +30 -59
- data/lib/hecks/bench/cli.rb +0 -74
- data/lib/hecks/bench/environment.rb +0 -100
- data/lib/hecks/bench/postgres_probe.rb +0 -41
- data/lib/hecks/bench/report.rb +0 -116
- data/lib/hecks/bench/ruby_runner.rb +0 -151
- data/lib/hecks/bench/run.rb +0 -55
- data/lib/hecks/bench/rust_runner.rb +0 -165
- data/lib/hecks/bench/stats.rb +0 -75
- data/lib/hecks/bench/suite.rb +0 -172
- data/lib/hecks/bench/workload.rb +0 -137
- data/lib/hecks/bench.rb +0 -28
- data/lib/hecks/codemod.rb +0 -443
- data/lib/hecks/corpus.rb +0 -479
- data/lib/hecks/doc/reference.rb +0 -585
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
- data/lib/hecks/fuzzing/combination_miner.rb +0 -178
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
- data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
- data/lib/hecks/fuzzing/differential.rb +0 -192
- data/lib/hecks/fuzzing/domain_generator.rb +0 -871
- data/lib/hecks/fuzzing/era_boundary.rb +0 -154
- data/lib/hecks/fuzzing/form_census.rb +0 -285
- data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
- data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
- data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
- data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
- data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
- data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
- data/lib/hecks/fuzzing/properties/guards.rb +0 -398
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
- data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
- data/lib/hecks/fuzzing/properties/querying.rb +0 -260
- data/lib/hecks/fuzzing/properties.rb +0 -267
- data/lib/hecks/fuzzing/qa_settings.rb +0 -164
- data/lib/hecks/fuzzing/replay.rb +0 -930
- data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
- data/lib/hecks/fuzzing/self_consistency.rb +0 -825
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
- data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
- data/lib/hecks/fuzzing/shrinker.rb +0 -309
- data/lib/hecks/fuzzing/structural_skips.rb +0 -53
- data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
- data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
- data/lib/hecks/fuzzing/value_generator.rb +0 -340
- data/lib/hecks/fuzzing.rb +0 -23
- data/lib/hecks/grammar/evolve.rb +0 -524
- data/lib/hecks/query_ir.rb +0 -482
|
@@ -1,69 +1,27 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
module MetaValidator
|
|
4
|
-
# Offers every declaration in a built bluebook to the meta-domain
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# real cost is any verb the language declares that the judge never
|
|
8
|
-
# offers — a branch nobody wrote for it — going undetected, since a
|
|
9
|
-
# branch that does not exist cannot fail. `Command.Argument` and
|
|
10
|
-
# `ValueObject.Field` were both admitted that way once, undetected;
|
|
11
|
-
# every rule hanging off them was decoration until offered for real.
|
|
12
|
-
#
|
|
13
|
-
# So instead the judge walks: it reads the plan the language makes of
|
|
14
|
-
# itself (Plan), and for each node offers the creating command, then
|
|
15
|
-
# each list through the command that appends to it, then each child. A
|
|
16
|
-
# verb in the plan with no offer is now impossible — there is no
|
|
17
|
-
# branch left in which to forget one, and spec/judge_coverage_spec
|
|
18
|
-
# holds it to that.
|
|
19
|
-
#
|
|
20
|
-
# What is not uniform lives in Readings, and only where the IR's shape
|
|
21
|
-
# differs from the language's. Naming differences do not appear at all: the
|
|
22
|
-
# language spells its fields as the IR spells them.
|
|
23
|
-
#
|
|
24
|
-
# Only the dispatch half of the round trip lives here. Reconstruction is the
|
|
25
|
-
# experiment's business ; judging does not need it.
|
|
4
|
+
# Offers every declaration in a built bluebook to the meta-domain by
|
|
5
|
+
# walking the plan itself, so no verb the language declares can go
|
|
6
|
+
# un-offered by omission.
|
|
26
7
|
class Judge
|
|
27
8
|
include Readings
|
|
28
9
|
|
|
29
|
-
#
|
|
30
|
-
#
|
|
31
|
-
# value objects have to exist before anything that can name one — an
|
|
32
|
-
# aggregate's own attributes, and an entity's own (M13: an entity is its
|
|
33
|
-
# own root, repeating the aggregate's whole shape one level down, so its
|
|
34
|
-
# attributes resolve against the same value-object pool). ValueObject
|
|
35
|
-
# first, Entity second, so an entity's own attributes are never offered
|
|
36
|
-
# before the value objects they may reference exist — a self-hosting
|
|
37
|
-
# casualty found live: the meta-grammar's own Handler/Dispatch/Member/
|
|
38
|
-
# Keyword/Argument entities (S17, ADR 0026) failed reference resolution
|
|
39
|
-
# on their own plain value-object-typed attributes (`HandlerText`,
|
|
40
|
-
# `MemberPosition`, ...) the moment entity attributes started being
|
|
41
|
-
# checked at all, because `@plan.names`' own (incidental) declaration
|
|
42
|
-
# order happened to walk Entity first. The order is stated here, not
|
|
43
|
-
# left to whatever order the plan's own category table iterates in —
|
|
44
|
-
# see `detail_node`'s own use of this constant, below.
|
|
10
|
+
# ValueObject before Entity: an entity's own attributes may
|
|
11
|
+
# reference a value object, which must exist before it resolves.
|
|
45
12
|
EAGER_CHILDREN = { "Aggregate" => %w[ValueObject Entity] }.freeze
|
|
46
13
|
|
|
47
|
-
#
|
|
48
|
-
#
|
|
49
|
-
#
|
|
50
|
-
# parent, because a category's parent is derived from the one `*_id` argument
|
|
51
|
-
# its creating command carries. This says the other edge out loud.
|
|
14
|
+
# Command and Query are reused for a piece's own commands/queries,
|
|
15
|
+
# since the plan derives a category's parent from its creating
|
|
16
|
+
# command's one `*_id` argument and cannot express a second parent.
|
|
52
17
|
WITHIN_ENTITY = %w[Command Query].freeze
|
|
53
18
|
|
|
54
19
|
attr_reader :refusals
|
|
55
20
|
|
|
56
|
-
#
|
|
57
|
-
#
|
|
58
|
-
# Judging a bluebook and holding one differ by exactly this: whether anyone
|
|
59
|
-
# keeps the runtime the declarations were dispatched into. Nobody did, so
|
|
60
|
-
# `spec/round_trip_spec` reached the records by `Judge.allocate` and four
|
|
61
|
-
# `instance_variable_set` calls. Reading the chapter back is the point now,
|
|
62
|
-
# not a curiosity, so the runtime is simply readable.
|
|
21
|
+
# The runtime dispatched into, not just the refusals, so a caller
|
|
22
|
+
# can read the resulting records back out.
|
|
63
23
|
attr_reader :runtime
|
|
64
24
|
|
|
65
|
-
# @param bluebook [Object] a built bluebook chapter graph, as
|
|
66
|
-
# `MetaValidator.call` receives it
|
|
67
25
|
def initialize(bluebook)
|
|
68
26
|
@bluebook = bluebook
|
|
69
27
|
@refusals = []
|
|
@@ -74,13 +32,9 @@ module Hecks
|
|
|
74
32
|
|
|
75
33
|
private
|
|
76
34
|
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
# An Integer stays an Integer : RowCount declares `attribute :value,
|
|
82
|
-
# Integer`, so stringifying a member count fails the type gate rather than
|
|
83
|
-
# feeding the rule it was meant to feed.
|
|
35
|
+
# nil stays nil so an optional field reads as undeclared rather
|
|
36
|
+
# than declared-empty; an Integer passes through raw so a typed
|
|
37
|
+
# field (RowCount's `value`) still hits its own type gate.
|
|
84
38
|
def v(text)
|
|
85
39
|
return nil if text.nil?
|
|
86
40
|
return { value: text } if text.is_a?(Integer)
|
|
@@ -88,14 +42,8 @@ module Hecks
|
|
|
88
42
|
{ value: text.to_s }
|
|
89
43
|
end
|
|
90
44
|
|
|
91
|
-
# A reference is
|
|
92
|
-
#
|
|
93
|
-
# Every other field goes to the meta-domain as a one-field value object,
|
|
94
|
-
# because that is what it is. A reference is not: it carries the id of a
|
|
95
|
-
# head, and wrapping an id in an object was the language saying `{value:
|
|
96
|
-
# "Banking::Customer"}` where it meant `"Banking::Customer"`. The plan
|
|
97
|
-
# answers which arguments those are, read from the language's own IR, so
|
|
98
|
-
# nothing here needs to know the names.
|
|
45
|
+
# A reference argument is passed as the bare id it names; every
|
|
46
|
+
# other field is wrapped as a one-field value object instead.
|
|
99
47
|
def carried(plan, verb, argument, value)
|
|
100
48
|
return v(value) unless plan && verb && plan.references?(verb, argument)
|
|
101
49
|
|
|
@@ -108,48 +56,25 @@ module Hecks
|
|
|
108
56
|
yield
|
|
109
57
|
rescue Runtime::GivenNotMet, Runtime::InvariantViolation,
|
|
110
58
|
Runtime::TypeMismatch, Runtime::NotFound => e
|
|
111
|
-
# NotFound is a verdict, not noise
|
|
112
|
-
# its value object, so "no ValueObject with id
|
|
113
|
-
# must use value-object types` refusing.
|
|
59
|
+
# NotFound is a verdict, not noise: an attribute's type is a
|
|
60
|
+
# reference to its value object, so "no ValueObject with id ..."
|
|
61
|
+
# is `attributes must use value-object types` refusing.
|
|
114
62
|
@refusals << "#{label}: #{e.message}"
|
|
115
63
|
rescue Runtime::UnknownVerb
|
|
116
64
|
nil
|
|
117
65
|
end
|
|
118
66
|
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
# `Value::Coercion#check_scalar_shapes` this construction is the
|
|
123
|
-
# language's own self-hosted grammar walk, not a real domain's
|
|
124
|
-
# command, so a String-typed meta-grammar field (`Normalise`'s
|
|
125
|
-
# `position`, a `RuleText` — `appends`' generic walk-index handling
|
|
126
|
-
# collides with that field's own name, see the flag's own comment
|
|
127
|
-
# in coercion.rb) may still arrive as the raw Integer `appends`
|
|
128
|
-
# hands it. Scoped to exactly this method: nothing outside a judge's
|
|
129
|
-
# own dispatch ever runs inside it, so an ordinary domain command
|
|
130
|
-
# (a real caller's own PieceId, Money, …) is never affected.
|
|
67
|
+
# Wrapped in judge_bootstrapping: the walk's own values sometimes
|
|
68
|
+
# arrive as raw types a real domain command would never accept,
|
|
69
|
+
# and only a judge's own dispatch should relax for that.
|
|
131
70
|
def send_to(verb, label, to: nil, **payload)
|
|
132
71
|
Runtime::Value.judge_bootstrapping do
|
|
133
72
|
offer(label) { @runtime.dispatch(verb, to: to, with: args(payload)) }
|
|
134
73
|
end
|
|
135
74
|
end
|
|
136
75
|
|
|
137
|
-
#
|
|
138
|
-
#
|
|
139
|
-
# `receiver` is an internal accumulator — it tracks the aggregate this
|
|
140
|
-
# walk is inside and, once it crosses into a real entity-owned category
|
|
141
|
-
# (Member/Handler/Dispatch — S17, ADR 0026), every entity hop on top of
|
|
142
|
-
# it. But `Routing.envelope`/`parse_envelope_hash` do not want that
|
|
143
|
-
# shape restated when there is no entity to route to: a plain aggregate
|
|
144
|
-
# command is addressed by its bare id (`Facade::Handle#dispatch` — "to:
|
|
145
|
-
# @id" — and `CommandRequest`'s own header: "aggregate command: { to:
|
|
146
|
-
# "record-id", ... }"), never `{aggregate:, entities: []}` — that hash
|
|
147
|
-
# is the entity route's own shape, degenerate with nothing in it.
|
|
148
|
-
#
|
|
149
|
-
# So this is the one place `receiver` turns into a `to:` value: bare
|
|
150
|
-
# when there is no entity hop (the overwhelming common case — every
|
|
151
|
-
# category but those three), the full envelope only when there
|
|
152
|
-
# genuinely is one.
|
|
76
|
+
# A bare id when there is no entity hop (the common case); the
|
|
77
|
+
# full {aggregate:, entities:} envelope only when there is one.
|
|
153
78
|
def address(receiver)
|
|
154
79
|
return receiver[:aggregate] if receiver[:entities].empty?
|
|
155
80
|
|
|
@@ -161,19 +86,9 @@ module Hecks
|
|
|
161
86
|
detail_node("Bluebook", @bluebook, nil, 0)
|
|
162
87
|
end
|
|
163
88
|
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
#
|
|
167
|
-
# — one sibling at a time would mean an aggregate's attributes are
|
|
168
|
-
# offered before its later siblings exist, so an attribute that
|
|
169
|
-
# points at another aggregate could only resolve if that aggregate
|
|
170
|
-
# happens to be declared earlier in the file: banking would survive
|
|
171
|
-
# on luck, Customer written above Account.
|
|
172
|
-
#
|
|
173
|
-
# So siblings are declared in one pass and detailed in a second. It is the
|
|
174
|
-
# same ordering the walk already used one level down — value objects before
|
|
175
|
-
# the attributes that name them — lifted to the level above, and it is what
|
|
176
|
-
# lets a reference be a reference rather than a string nobody can check.
|
|
89
|
+
# Every sibling is declared before any is detailed, so one
|
|
90
|
+
# sibling's attribute can reference another declared later in
|
|
91
|
+
# the same file.
|
|
177
92
|
def declare_node(category, node, parent_id, index, extra = {}, receiver: nil)
|
|
178
93
|
plan = @plan.category(category)
|
|
179
94
|
return unless plan
|
|
@@ -186,51 +101,21 @@ module Hecks
|
|
|
186
101
|
return unless plan
|
|
187
102
|
|
|
188
103
|
id = identify(category, parent_id, node, index)
|
|
189
|
-
# `extra`
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
#
|
|
193
|
-
# adds this node's own on top — computed for every category,
|
|
194
|
-
# entity-owned or not, because a node need not be entity-owned
|
|
195
|
-
# itself to own one (ValueObject isn't, and Member still needs
|
|
196
|
-
# its `aggregate:`/`name:`) — it is simply what this node's own
|
|
197
|
-
# `identified_by` resolves to, the same fields `identify` two
|
|
198
|
-
# lines up already derives the joined id from.
|
|
199
|
-
#
|
|
200
|
-
# `own` is the subset actually spent on a dispatch payload —
|
|
201
|
-
# only when this category is itself entity-owned, since an
|
|
202
|
-
# ordinary category (Command's own "Rule"/"Argument", offered
|
|
203
|
-
# through the same `extra` slot for a different reason, see
|
|
204
|
-
# `within_entity` below) locates the record it attaches to
|
|
205
|
-
# through the parent id `id:` already carries, and merging
|
|
206
|
-
# unrecognized `aggregate:`/`entity_id:` into their payload
|
|
207
|
-
# would have the runtime refuse them for an argument they
|
|
208
|
-
# never declared.
|
|
104
|
+
# `extra` carries every entity-owned ancestor's identity down to
|
|
105
|
+
# this node; an ordinary category ignores it and locates its
|
|
106
|
+
# record through `id:` instead, so merging it in would be
|
|
107
|
+
# refused as an unrecognized argument.
|
|
209
108
|
identity = extra.merge(node_identity(plan, category, node, index, parent_id))
|
|
210
109
|
receiver ||= { aggregate: id, entities: [] }
|
|
211
110
|
eager, later = children_of(category).partition { |child| eager?(category, child) }
|
|
212
|
-
#
|
|
213
|
-
#
|
|
214
|
-
# accident of which .bluebook file registered which category first,
|
|
215
|
-
# never a promise about which of two eager children exists before the
|
|
216
|
-
# other. `EAGER_CHILDREN`'s own array is that promise (ValueObject
|
|
217
|
-
# before Entity), so the walk keeps only what this parent actually
|
|
218
|
-
# has, in the order the constant states — see that constant's own
|
|
219
|
-
# comment for the bug this exact reordering fixes.
|
|
111
|
+
# `children_of`'s order is incidental (plan registration order);
|
|
112
|
+
# keep only what EAGER_CHILDREN promises, in the order it does.
|
|
220
113
|
eager = Array(EAGER_CHILDREN[category]) & eager
|
|
221
114
|
|
|
222
115
|
eager.each { |child| walk_all(child, node, id, entity_child_extra(child, identity), receiver: receiver) }
|
|
223
116
|
setters(plan, category, node, receiver)
|
|
224
|
-
# Before `appends
|
|
225
|
-
#
|
|
226
|
-
# (M13): a piece nested inside a piece (Handler's own
|
|
227
|
-
# `dispatches, list_of(Dispatch)` — S17, ADR 0026) must exist
|
|
228
|
-
# before this piece's own attribute list can reference it as a
|
|
229
|
-
# held entity, the same way `Account#ledger` needs Account's own
|
|
230
|
-
# entities walked eagerly. `nest_entities` is a no-op for every
|
|
231
|
-
# category but "Entity" (its own early return), so reordering it
|
|
232
|
-
# ahead of `appends` costs nothing for anything else that walks
|
|
233
|
-
# through here.
|
|
117
|
+
# Before `appends`: a nested entity referenced from this node's
|
|
118
|
+
# own attribute list must exist before that list is walked.
|
|
234
119
|
nest_entities(category, node, id, parent_id)
|
|
235
120
|
appends(plan, category, node, receiver, parent_id)
|
|
236
121
|
later.each { |child| walk_all(child, node, id, entity_child_extra(child, identity), receiver: receiver) }
|
|
@@ -238,42 +123,16 @@ module Hecks
|
|
|
238
123
|
sealers(plan, category, receiver)
|
|
239
124
|
end
|
|
240
125
|
|
|
241
|
-
#
|
|
242
|
-
#
|
|
243
|
-
#
|
|
244
|
-
# `detail_node` itself (regardless of whether each ancestor is
|
|
245
|
-
# itself entity-owned — ValueObject contributes its own `aggregate:
|
|
246
|
-
# `/`name:` to Member's payload despite being an ordinary top-
|
|
247
|
-
# level category), so there is nothing left to re-derive here. An
|
|
248
|
-
# ordinary child (one with a real top-level aggregate of its own
|
|
249
|
-
# to dispatch a bare verb into) needs none of it.
|
|
126
|
+
# Only an entity-owned child needs the accumulated ancestor
|
|
127
|
+
# identity; an ordinary child dispatches through its own
|
|
128
|
+
# top-level aggregate.
|
|
250
129
|
def entity_child_extra(child, identity)
|
|
251
130
|
@plan.category(child)&.entity_owned ? identity : {}
|
|
252
131
|
end
|
|
253
132
|
|
|
254
|
-
#
|
|
255
|
-
#
|
|
256
|
-
#
|
|
257
|
-
# walks more than one level (Handler -> Dispatch) and each level
|
|
258
|
-
# needs the same three answered about itself, not just the first:
|
|
259
|
-
#
|
|
260
|
-
# the parent link (plan.parent_key) -> `parent_id`, the id
|
|
261
|
-
# the walk already carries in from one level up
|
|
262
|
-
# a walk-minted one (`POSITION`) -> the walk index itself ;
|
|
263
|
-
# never a stored field (Member's own header:
|
|
264
|
-
# "position is not a mint — it is read straight
|
|
265
|
-
# out of the source file")
|
|
266
|
-
# a real field (anything else) -> `field_value`, same
|
|
267
|
-
# reader every other field in this file uses
|
|
268
|
-
# (Handler's own `event_type`, Dispatch's own
|
|
269
|
-
# `command_name`)
|
|
270
|
-
#
|
|
271
|
-
# `carried` still decides bare-vs-wrapped the normal way ; `POSITION`
|
|
272
|
-
# is the one case with no verb to ask `carried` about (`plan.
|
|
273
|
-
# declare` is always nil for an entity-owned category — Plan#read's
|
|
274
|
-
# own comment says why), so it is minted straight as a value object,
|
|
275
|
-
# matching exactly what `declare`'s own field loop already mints a
|
|
276
|
-
# `POSITION` field as.
|
|
133
|
+
# Each identity field comes from one of three places: the parent
|
|
134
|
+
# link, the walk's own index (`POSITION`), or a real field read off
|
|
135
|
+
# the node.
|
|
277
136
|
def node_identity(plan, category, node, index, parent_id)
|
|
278
137
|
plan.identity_paths.each_with_object({}) do |path, fields|
|
|
279
138
|
head = path.to_s.split(".").first
|
|
@@ -288,26 +147,19 @@ module Hecks
|
|
|
288
147
|
end
|
|
289
148
|
end
|
|
290
149
|
|
|
291
|
-
#
|
|
292
|
-
#
|
|
293
|
-
#
|
|
294
|
-
#
|
|
295
|
-
# Dispatch's own parent, Handler, is itself entity-owned (S17,
|
|
296
|
-
# ADR 0026's two-level chain — `ProcessManager.Handler.Dispatch`),
|
|
297
|
-
# so this recurses rather than reading one level and stopping.
|
|
150
|
+
# An ordinary category's own top-level aggregate reaches every
|
|
151
|
+
# verb bare; an entity-owned one prefixes its parent's own dotted
|
|
152
|
+
# path instead (ADR 0026), since a nested entity's parent may
|
|
153
|
+
# itself be entity-owned.
|
|
298
154
|
def dotted_prefix(plan)
|
|
299
155
|
return plan.name unless plan.entity_owned
|
|
300
156
|
|
|
301
157
|
"#{dotted_prefix(@plan.category(plan.parent))}.#{plan.name}"
|
|
302
158
|
end
|
|
303
159
|
|
|
304
|
-
# Entity-owned categories have no top-level aggregate
|
|
305
|
-
#
|
|
306
|
-
#
|
|
307
|
-
# (`Dispatch`, inside `Handler`) reaches it as `ProcessManager.
|
|
308
|
-
# Handler.Dispatch.Bind` — the dotted shape `EntityInterpreter#call`
|
|
309
|
-
# already splits any real entity's own verb into, one hop per
|
|
310
|
-
# segment (`walk_entity_chain`, entity_interpreter.rb).
|
|
160
|
+
# Entity-owned categories have no top-level aggregate to route a
|
|
161
|
+
# bare verb into, so the verb is addressed by this category's
|
|
162
|
+
# full dotted path instead.
|
|
311
163
|
def verb_for(plan, verb)
|
|
312
164
|
"#{dotted_prefix(plan)}.#{verb}"
|
|
313
165
|
end
|
|
@@ -329,15 +181,10 @@ module Hecks
|
|
|
329
181
|
end
|
|
330
182
|
end
|
|
331
183
|
|
|
332
|
-
#
|
|
333
|
-
#
|
|
334
|
-
#
|
|
335
|
-
#
|
|
336
|
-
# keeps its own `_id` — an explicit `as:` on `reference_to Entity`,
|
|
337
|
-
# never touched by ADR 0025's rename (only the default, un-aliased
|
|
338
|
-
# mint dropped the suffix; `aggregate` did precisely because
|
|
339
|
-
# `Command#reference_to Aggregate`/`Query#reference_to Aggregate`
|
|
340
|
-
# carry no `as:` of their own).
|
|
184
|
+
# Addressed under the piece so a command name can't collide
|
|
185
|
+
# between an aggregate and one of its entities; `aggregate` says
|
|
186
|
+
# what a reference resolves against, `entity_id` says which
|
|
187
|
+
# piece declared it.
|
|
341
188
|
def within_entity(category, node, id, aggregate)
|
|
342
189
|
return unless category == "Entity"
|
|
343
190
|
|
|
@@ -350,30 +197,10 @@ module Hecks
|
|
|
350
197
|
end
|
|
351
198
|
end
|
|
352
199
|
|
|
353
|
-
# An entity may nest further entities
|
|
354
|
-
#
|
|
355
|
-
#
|
|
356
|
-
#
|
|
357
|
-
# cannot express this through `children_of`/`EAGER_CHILDREN` the
|
|
358
|
-
# way Aggregate's own entities/value_objects can — there is only
|
|
359
|
-
# one "Entity" Plan category, describing what any entity looks
|
|
360
|
-
# like, not one per nesting level — so this recurses by hand,
|
|
361
|
-
# the same special case `within_entity` (above) already is for
|
|
362
|
-
# Command/Query.
|
|
363
|
-
#
|
|
364
|
-
# `owner` is the field this repurposes — `entity.bluebook`
|
|
365
|
-
# declares it (`attribute :owner, EntityText`) and it has held
|
|
366
|
-
# exactly one value since ADR 0025's rename: the same id
|
|
367
|
-
# `aggregate` already carries, kept as a wrapped-text copy,
|
|
368
|
-
# never read back anywhere else in this codebase (grep finds no
|
|
369
|
-
# second reference). For a nested entity, the two finally
|
|
370
|
-
# diverge — `aggregate` stays the root (Dispatch resolves
|
|
371
|
-
# exactly the way any other Entity record does, by its root
|
|
372
|
-
# aggregate), and `owner` becomes this entity's own direct
|
|
373
|
-
# parent (Handler, not ProcessManager) — which is exactly the
|
|
374
|
-
# fact `Reconstruction#direct_entities` needs to tell a
|
|
375
|
-
# root-level entity apart from a nested one sharing the same
|
|
376
|
-
# root.
|
|
200
|
+
# An entity may nest further entities (ADR 0026): `aggregate`
|
|
201
|
+
# stays the walk's root, while `owner` is this entity's own
|
|
202
|
+
# direct parent — what tells a nested entity apart from a
|
|
203
|
+
# root-level one sharing that same root.
|
|
377
204
|
def nest_entities(category, node, id, aggregate)
|
|
378
205
|
return unless category == "Entity"
|
|
379
206
|
|
|
@@ -384,16 +211,11 @@ module Hecks
|
|
|
384
211
|
})
|
|
385
212
|
end
|
|
386
213
|
|
|
387
|
-
# Where
|
|
388
|
-
# node
|
|
389
|
-
#
|
|
390
|
-
# comes from the node. Without this, declaration order would survive only
|
|
391
|
-
# because the meta store happens to iterate in insertion order — an
|
|
392
|
-
# accident that an ask ordered any other way would take away, and
|
|
393
|
-
# Reconstruction is the one reader that must have the source's order
|
|
394
|
-
# rather than a stable one.
|
|
214
|
+
# Where a node sits among siblings is a fact about the walk, not
|
|
215
|
+
# the node, so the walk supplies it rather than reading a stored
|
|
216
|
+
# field; Reconstruction depends on this being the source order.
|
|
395
217
|
# `private` above has no effect on a constant; kept here anyway,
|
|
396
|
-
# beside the method that reads it
|
|
218
|
+
# beside the method that reads it.
|
|
397
219
|
# rubocop:disable-next Lint/UselessConstantScoping
|
|
398
220
|
POSITION = "position".freeze
|
|
399
221
|
|
|
@@ -413,10 +235,9 @@ module Hecks
|
|
|
413
235
|
send_to("Bluebook::#{verb_for(plan, plan.declare)}", id, to: id, **payload.merge(extra))
|
|
414
236
|
end
|
|
415
237
|
|
|
416
|
-
# A setter whose every source is absent is not dispatched
|
|
417
|
-
#
|
|
418
|
-
#
|
|
419
|
-
# bluebook that is perfectly well formed.
|
|
238
|
+
# A setter whose every source is absent is not dispatched —
|
|
239
|
+
# offering "" would make a rule refuse a bluebook that is
|
|
240
|
+
# well-formed.
|
|
420
241
|
def setters(plan, category, node, receiver)
|
|
421
242
|
plan.setters.each do |setter|
|
|
422
243
|
payload = setter.targets.to_h do |target, argument|
|
|
@@ -434,10 +255,8 @@ module Hecks
|
|
|
434
255
|
plan.appends.each do |list_name, append|
|
|
435
256
|
rows_for(category, list_name, node).each_with_index do |row, index|
|
|
436
257
|
chosen = append_for(category, list_name, append, row, node)
|
|
437
|
-
# `position` is the walk index
|
|
438
|
-
#
|
|
439
|
-
# S17) is ordered by where the walk found it, never by a field the
|
|
440
|
-
# row happens to hold.
|
|
258
|
+
# `position` is the walk index, as in `declare`: an appended
|
|
259
|
+
# element is ordered by where the walk found it.
|
|
441
260
|
payload = chosen.map.to_h do |field, argument|
|
|
442
261
|
value = if field.to_s == POSITION
|
|
443
262
|
v(index)
|
|
@@ -454,16 +273,10 @@ module Hecks
|
|
|
454
273
|
end
|
|
455
274
|
end
|
|
456
275
|
|
|
457
|
-
#
|
|
458
|
-
# resolve against
|
|
459
|
-
#
|
|
460
|
-
#
|
|
461
|
-
# comment on why); its attributes read the same pool its
|
|
462
|
-
# enclosing aggregate declares, one level up the construct tree
|
|
463
|
-
# no matter how many entities deep this attribute is nested —
|
|
464
|
-
# `parent_id` names it because `detail_node`/`nest_entities`
|
|
465
|
-
# thread the root aggregate's id down as `parent_id` at every
|
|
466
|
-
# entity level, never the direct (possibly entity) parent.
|
|
276
|
+
# An entity has no value objects of its own; its attributes
|
|
277
|
+
# resolve against its enclosing aggregate's pool, so the root
|
|
278
|
+
# aggregate id (`parent_id`, not the direct parent) is what this
|
|
279
|
+
# returns for it.
|
|
467
280
|
def owning_aggregate_ref(category, id, parent_id)
|
|
468
281
|
category == "Entity" ? parent_id : id
|
|
469
282
|
end
|
|
@@ -473,68 +286,36 @@ module Hecks
|
|
|
473
286
|
plan.sealers.each { |verb| send_to("Bluebook::#{verb_for(plan, verb)}", id, to: address(receiver)) }
|
|
474
287
|
end
|
|
475
288
|
|
|
476
|
-
# An
|
|
477
|
-
#
|
|
478
|
-
#
|
|
479
|
-
#
|
|
480
|
-
# predicate — for a head's own attributes, aggregate or entity alike: an
|
|
481
|
-
# entity is its own root, repeating the aggregate's whole shape one level
|
|
482
|
-
# down (entity.rb's own words), and an undeclared type on an entity's
|
|
483
|
-
# attribute must fail the same reference resolution an aggregate's own
|
|
484
|
-
# does, not go unchecked because only "Aggregate.attributes" was ever
|
|
485
|
-
# asked.
|
|
486
|
-
# An attribute's type is offered as the ID of the thing it names, so the
|
|
487
|
-
# language resolves it as a reference and "the type is declared" costs no
|
|
488
|
-
# predicate. Three kinds, three ids: a value object and an entity both hang
|
|
489
|
-
# off this aggregate, so they share its prefix; another aggregate's head
|
|
490
|
-
# hangs off the chapter.
|
|
289
|
+
# An attribute's type is offered as the id of the value object it
|
|
290
|
+
# names, so "attributes must use value-object types" is enforced
|
|
291
|
+
# by reference resolution rather than a predicate — for an
|
|
292
|
+
# entity's own attributes too, since an entity is its own root.
|
|
491
293
|
def cell(category, list_name, row, field, id, append, aggregate_id)
|
|
492
294
|
value = row_value(row, field)
|
|
493
|
-
# A default keeps its type by being written as a literal
|
|
494
|
-
# "0.0"
|
|
295
|
+
# A default keeps its type by being written as a literal (0.0,
|
|
296
|
+
# not "0.0"): the language holds it as text, and text alone forgets.
|
|
495
297
|
return encode_literal(value) if field == :default
|
|
496
298
|
return value unless field == :type
|
|
497
|
-
# A reference names another head wherever it
|
|
498
|
-
# a command,
|
|
499
|
-
# id in all four
|
|
500
|
-
#
|
|
501
|
-
# type is text and stays text.
|
|
299
|
+
# A reference names another head wherever it's written (on a
|
|
300
|
+
# head, a command, a piece, or an ask), so it's offered as that
|
|
301
|
+
# head's id in all four; only a head's own attributes further
|
|
302
|
+
# qualify a plain type into a value object's id.
|
|
502
303
|
return points_at(row, id) if append.verb == "Reference"
|
|
503
304
|
return value unless attribute_list?(category, list_name)
|
|
504
305
|
|
|
505
306
|
Naming.identity([owning_aggregate_id(aggregate_id, value), value])
|
|
506
307
|
end
|
|
507
308
|
|
|
508
|
-
# A head's own attributes
|
|
509
|
-
#
|
|
510
|
-
#
|
|
511
|
-
# fields), and a type written there is a name, not a reference — the same
|
|
512
|
-
# distinction `cell`'s own comment draws.
|
|
309
|
+
# A head's own attributes (an aggregate's, or an entity's own
|
|
310
|
+
# root). Every other "attributes" list belongs to something that
|
|
311
|
+
# isn't a head, so a type written there is a name, not a reference.
|
|
513
312
|
def attribute_list?(category, list_name)
|
|
514
313
|
list_name.to_s == "attributes" && %w[Aggregate Entity].include?(category)
|
|
515
314
|
end
|
|
516
315
|
|
|
517
|
-
#
|
|
518
|
-
#
|
|
519
|
-
#
|
|
520
|
-
# TranslationAggregate's own `was`/every rename-rule's own `from`/
|
|
521
|
-
# `to`/... all deliberately reuse the sibling "Translation"
|
|
522
|
-
# aggregate's own `TranslationName` (that file's own header:
|
|
523
|
-
# "the shared TranslationName every non-identity field below
|
|
524
|
-
# uses"), a real, intentional cross-aggregate reuse — not the
|
|
525
|
-
# local-only ownership every other real domain in this corpus
|
|
526
|
-
# happens to have used until now.
|
|
527
|
-
#
|
|
528
|
-
# `id` (already `Naming.identity([chapter, aggregate])`-joined)
|
|
529
|
-
# only ever composes with the local aggregate for real, non-
|
|
530
|
-
# entity-owned attributes — an entity's own `id` never matches
|
|
531
|
-
# any top-level aggregate here, so `local` stays nil and this
|
|
532
|
-
# returns `id` unchanged, exactly the prior behavior. Same for
|
|
533
|
-
# every attribute whose type is locally declared (the overwhelming
|
|
534
|
-
# common case, Banking's own Customer/Account included) — this
|
|
535
|
-
# only ever changes the answer when the local aggregate does not
|
|
536
|
-
# declare `value` itself, falling back to the first (declaration-
|
|
537
|
-
# order) other aggregate in the same chapter that does.
|
|
316
|
+
# A value object's type may be declared on a different aggregate
|
|
317
|
+
# in the same chapter; the local aggregate is tried first, then
|
|
318
|
+
# the first (declaration-order) other aggregate that declares it.
|
|
538
319
|
def owning_aggregate_id(id, value)
|
|
539
320
|
local = @bluebook.aggregates.find { |aggregate| Naming.identity([@bluebook.name, aggregate.name]) == id }
|
|
540
321
|
return id unless local
|
|
@@ -546,37 +327,20 @@ module Hecks
|
|
|
546
327
|
Naming.identity([@bluebook.name, owner.name])
|
|
547
328
|
end
|
|
548
329
|
|
|
549
|
-
#
|
|
550
|
-
#
|
|
551
|
-
#
|
|
552
|
-
# which collection to search here without re-deriving that same
|
|
553
|
-
# decision, so this simply checks both. The self-hosted grammar's
|
|
554
|
-
# own Bluebook:Syntax#attributes proved entities need the same
|
|
555
|
-
# cross-aggregate fallback value objects do — Syntax's own
|
|
556
|
-
# `Argument`-typed attribute names Command's entity, not one of
|
|
557
|
-
# Syntax's own.
|
|
330
|
+
# Checks both value objects and entities this aggregate declares:
|
|
331
|
+
# the caller already knows which verb it dispatches, not which
|
|
332
|
+
# collection to search, without re-deriving that here.
|
|
558
333
|
def names?(aggregate, value)
|
|
559
334
|
aggregate.value_objects.any? { |vo| vo.hecks_name == value } ||
|
|
560
335
|
aggregate.entities.any? { |entity| entity.hecks_name == value }
|
|
561
336
|
end
|
|
562
337
|
|
|
563
|
-
#
|
|
564
|
-
#
|
|
565
|
-
#
|
|
566
|
-
#
|
|
567
|
-
#
|
|
568
|
-
#
|
|
569
|
-
#
|
|
570
|
-
# Nothing is skipped any more. Reference and Holds did not exist, so the
|
|
571
|
-
# walk dropped both kinds and the meta-domain silently did not contain
|
|
572
|
-
# Account#customer_id or Account#ledger.
|
|
573
|
-
# Each alternate carries its own map, read from the language. Borrowing the
|
|
574
|
-
# primary's map dispatched `type:` where Reference declares `points_at:`,
|
|
575
|
-
# and the payload gate caught it — which is the gate paying for itself.
|
|
576
|
-
# `reference_to` can be written in four places — on a head, a command, a
|
|
577
|
-
# piece, an ask — and each keeps its own list of attributes, so each
|
|
578
|
-
# needs the Reference alternate. Only a head can hold a piece, so Holds
|
|
579
|
-
# stays where it was.
|
|
338
|
+
# The row itself decides which verb an attribute belongs to:
|
|
339
|
+
# Attribute for a value-object type, Reference<X> for another
|
|
340
|
+
# aggregate's head, Holds for an entity this aggregate declares.
|
|
341
|
+
# Each alternate carries its own field map — borrowing the
|
|
342
|
+
# primary's would dispatch `type:` where Reference declares
|
|
343
|
+
# `points_at:`.
|
|
580
344
|
def append_for(category, list_name, append, row, node)
|
|
581
345
|
return append unless list_name.to_s == "attributes"
|
|
582
346
|
return alternate(category, "Reference") || append if reference_row?(row)
|
|
@@ -591,28 +355,19 @@ module Hecks
|
|
|
591
355
|
|
|
592
356
|
def reference_row?(row) = row.respond_to?(:reference?) && row.reference?
|
|
593
357
|
|
|
594
|
-
# Only a head declares pieces
|
|
595
|
-
#
|
|
596
|
-
# answer `entities
|
|
358
|
+
# Only a head declares pieces; since every attribute list reaches
|
|
359
|
+
# here now, `node` may be a command, a piece or an ask, none of
|
|
360
|
+
# which answer `entities`.
|
|
597
361
|
def entity_row?(row, node)
|
|
598
362
|
return false unless node.respond_to?(:entities)
|
|
599
363
|
|
|
600
364
|
Array(node.entities).any? { |entity| entity.hecks_name == row.type.to_s }
|
|
601
365
|
end
|
|
602
366
|
|
|
603
|
-
# A record's
|
|
604
|
-
#
|
|
605
|
-
#
|
|
606
|
-
#
|
|
607
|
-
# This was a branch per category: "#{parent}::#{name}" for an aggregate,
|
|
608
|
-
# "#{parent}.#{name}" for most, "#{parent}##{index}" for the three that had
|
|
609
|
-
# no name to use. It was the composite identity all along, hand-written here
|
|
610
|
-
# because the language could not say it — which is why the language having
|
|
611
|
-
# no identity of its own and this method existing were the same fact.
|
|
612
|
-
#
|
|
613
|
-
# A part resolves from one of three places, and the declaration says which:
|
|
614
|
-
# the parent reference is the walk's parent_id, `position` is where the walk
|
|
615
|
-
# is, and anything else is read off the node.
|
|
367
|
+
# A record's id is its declared identity, joined the same way the
|
|
368
|
+
# runtime joins it, so there is exactly one way to name a thing.
|
|
369
|
+
# Each part comes from the parent link, the walk index
|
|
370
|
+
# (`position`), or a field read off the node.
|
|
616
371
|
def identify(category, parent_id, node, index)
|
|
617
372
|
plan = @plan.category(category)
|
|
618
373
|
return declared_name(node) unless plan
|
|
@@ -620,17 +375,13 @@ module Hecks
|
|
|
620
375
|
Naming.identity(plan.identity_paths.map { |path| identity_part(plan, path, parent_id, node, index, category) })
|
|
621
376
|
end
|
|
622
377
|
|
|
623
|
-
#
|
|
624
|
-
# whichever record is walking this one right now, aggregate
|
|
625
|
-
#
|
|
626
|
-
#
|
|
627
|
-
#
|
|
628
|
-
# would be a lie about which), so it cannot be read through
|
|
629
|
-
# `field_value` ; it is read the same way `plan.parent_key` already is,
|
|
630
|
-
# because it is that fact, spelled for the walk's immediate parent
|
|
631
|
-
# rather than for one specific kind of one.
|
|
378
|
+
# `owner_id` is a second reserved head (beside `position`): it
|
|
379
|
+
# names whichever record is walking this one right now, aggregate
|
|
380
|
+
# or entity, so Command/Query address the right piece. It is
|
|
381
|
+
# never a declared attribute, so it can't be read through
|
|
382
|
+
# `field_value`.
|
|
632
383
|
# `private` above has no effect on a constant; kept here anyway,
|
|
633
|
-
# beside the method that reads it
|
|
384
|
+
# beside the method that reads it.
|
|
634
385
|
# rubocop:disable-next Lint/UselessConstantScoping
|
|
635
386
|
OWNER = "owner_id".freeze
|
|
636
387
|
|
|
@@ -642,8 +393,8 @@ module Hecks
|
|
|
642
393
|
v_scalar(field_value(category, node, head.to_sym, parent_id))
|
|
643
394
|
end
|
|
644
395
|
|
|
645
|
-
# The scalar inside whatever the reading handed back
|
|
646
|
-
# a value object is not.
|
|
396
|
+
# The scalar inside whatever the reading handed back: a name is
|
|
397
|
+
# already one, a value object is not.
|
|
647
398
|
def v_scalar(held)
|
|
648
399
|
return held.to_s unless held.respond_to?(:to_h) && !held.is_a?(String)
|
|
649
400
|
|
|
@@ -656,10 +407,9 @@ module Hecks
|
|
|
656
407
|
|
|
657
408
|
def eager?(category, child) = Array(EAGER_CHILDREN[category]).include?(child)
|
|
658
409
|
|
|
659
|
-
# Command -> commands, ValueObject -> value_objects, Query ->
|
|
660
|
-
#
|
|
661
|
-
#
|
|
662
|
-
# second one risks disagreeing with it — see Naming.plural.
|
|
410
|
+
# Command -> commands, ValueObject -> value_objects, Query ->
|
|
411
|
+
# queries: convention, not a table. Naming.plural is kept as the
|
|
412
|
+
# single implementation, so a second one can't disagree with it.
|
|
663
413
|
def collection_reader(category) = Naming.plural(Naming.snake(category))
|
|
664
414
|
end
|
|
665
415
|
end
|