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,68 +1,19 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
module DSL
|
|
4
|
-
# `identified_by
|
|
5
|
-
#
|
|
6
|
-
# resolve_pending_identity! go"): a piece's own identity cannot
|
|
7
|
-
# spell differently from its aggregate's, and until this slice it
|
|
8
|
-
# was hand-duplicated onto both rather than shared.
|
|
9
|
-
#
|
|
10
|
-
# A separate module from AttributeCollector on purpose — every
|
|
11
|
-
# `attribute()`-taking builder (Command, Query, PortOperation,
|
|
12
|
-
# ValueObject, ...) `include`s that one too, and none of them
|
|
13
|
-
# declares an identity of its own ; folding `identified_by` in
|
|
14
|
-
# there made it answer for six builders that never earned the
|
|
15
|
-
# word (`syntax_conformance_spec.rb` catches exactly this — a
|
|
16
|
-
# builder answering a method the grammar never grants it).
|
|
17
|
-
#
|
|
18
|
-
# Requires its includer to also `include AttributeCollector`
|
|
19
|
-
# (for `attributes`/`resolve_identity_field!`/`resolve_identity_
|
|
20
|
-
# type!`, still declared there since every includer of that
|
|
21
|
-
# module needs them) and to supply `identity_pool` (private) —
|
|
22
|
-
# the value-object list a bare field's own type resolves
|
|
23
|
-
# against: AggregateBuilder's own `@value_objects + closed_sets`,
|
|
24
|
-
# or EntityBuilder's owner's, since a piece mints none of its own.
|
|
4
|
+
# `identified_by`, shared by AggregateBuilder and EntityBuilder (ADR 0025).
|
|
5
|
+
# The includer must include AttributeCollector and define a private `identity_pool`.
|
|
25
6
|
module IdentityDeclaration
|
|
26
|
-
# Records which
|
|
27
|
-
# resolution until build time.
|
|
28
|
-
#
|
|
29
|
-
# There are three live forms, deliberately distinguishable at the
|
|
30
|
-
# declaration site:
|
|
7
|
+
# Records which `identified_by` form a builder declared; resolution waits for build time.
|
|
31
8
|
#
|
|
32
9
|
# identified_by AccountNumber, as: :number # one identity concept
|
|
33
10
|
# identified_by do ... end # a bespoke concept
|
|
34
11
|
# identified_by :branch, :number # an existing compound key
|
|
35
12
|
#
|
|
36
|
-
#
|
|
37
|
-
#
|
|
38
|
-
#
|
|
39
|
-
#
|
|
40
|
-
# `calls:` column, so `GenericDispatch` forwards `identified_by` here unchanged, both
|
|
41
|
-
# after boot (reading the live grammar table) and during it
|
|
42
|
-
# (`GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`, which carries every `calls:`-routed row
|
|
43
|
-
# unconditionally, not a hand-picked bootstrap-reachable subset — though this one is
|
|
44
|
-
# exercised during boot too, since every self-hosted aggregate/entity declares an identity).
|
|
45
|
-
# Dispatches across the three live forms documented above (value-
|
|
46
|
-
# object + block, single type target, single/compound field
|
|
47
|
-
# target), each an early return that sets exactly one pending
|
|
48
|
-
# ivar. Splitting per form would need each branch's own `return`-
|
|
49
|
-
# with-nil semantics and the shared `@name`/`identity_pool`
|
|
50
|
-
# threaded back out as parameters, for no gain beyond what the
|
|
51
|
-
# three-forms comment above already documents.
|
|
52
|
-
#
|
|
53
|
-
# @param targets [Array<Symbol, Module>] zero or more identity targets: a value-object
|
|
54
|
-
# type (a bareword, resolved by `ConstShim` to a `Module`), one or more attribute-name
|
|
55
|
-
# symbols for a field or compound key, or empty when `definition` is given
|
|
56
|
-
# @param as [Symbol, nil] the field name to mint for a value-object-type target; not
|
|
57
|
-
# accepted with a field or compound-key target
|
|
58
|
-
# @yield a bespoke value-object body, `instance_eval`'d by `ValueObjectBuilder.build` to
|
|
59
|
-
# mint the identity's own anonymous value object
|
|
60
|
-
# @return [Array<Symbol>, Array<String>, nil] `targets` when a compound key is declared,
|
|
61
|
-
# the resolved identity paths from `legacy_identified_by` in shadow-parsing mode, or
|
|
62
|
-
# `nil` otherwise; callers reach this through `GenericDispatch`, which discards it
|
|
63
|
-
# @raise [Bluebook::DSL::Malformed] if `identified_by` was already called, combines a
|
|
64
|
-
# block with targets, names no identity, mixes a value-object type with field names,
|
|
65
|
-
# passes `as:` with a field or compound key, or the block declares no attributes
|
|
13
|
+
# @param targets [Array<Symbol, Module>] a value-object type or attribute names
|
|
14
|
+
# @param as [Symbol, nil] the field name to mint for a value-object-type target
|
|
15
|
+
# @yield a bespoke value-object body for the identity's own value object
|
|
16
|
+
# @raise [Bluebook::DSL::Malformed] on a repeat declaration or an invalid mix of forms
|
|
66
17
|
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
|
67
18
|
def identified_by_impl(*targets, as: nil, &definition)
|
|
68
19
|
return legacy_identified_by(*targets, as: as, &definition) if MetaValidator.shadow_parsing?
|
|
@@ -84,20 +35,8 @@ module Hecks
|
|
|
84
35
|
&definition
|
|
85
36
|
)
|
|
86
37
|
rescue NameError => e
|
|
87
|
-
#
|
|
88
|
-
#
|
|
89
|
-
# on to know a normal parse genuinely could not read this text
|
|
90
|
-
# (only `Malformed` triggers its shadow-mode retry, era_guard.rb's
|
|
91
|
-
# own comment). The old `identified_by { name.value }` — a block
|
|
92
|
-
# whose text was never called, only extracted (legacy_
|
|
93
|
-
# identified_by, below) — is exactly this shape: read under the
|
|
94
|
-
# current grammar it is instead instance_eval'd as a value-object
|
|
95
|
-
# definition, and a bare identifier like `name` inside it resolves
|
|
96
|
-
# to nothing WordGate#method_missing recognizes, so Ruby itself
|
|
97
|
-
# raises NameError. Left uncaught, that NameError skipped
|
|
98
|
-
# shadow_parse's rescue entirely and reached callers as a raw
|
|
99
|
-
# crash instead of the frozen-era fallback that exists for
|
|
100
|
-
# precisely this text.
|
|
38
|
+
# Must raise Malformed: EraGuard.shadow_parse retries frozen text only on
|
|
39
|
+
# Malformed, and a bare identifier in an old block form raises NameError here.
|
|
101
40
|
raise Malformed,
|
|
102
41
|
"#{@name}.identified_by do ... end could not be read as a value-object " \
|
|
103
42
|
"definition: #{e.message}"
|
|
@@ -122,10 +61,7 @@ module Hecks
|
|
|
122
61
|
raise Malformed,
|
|
123
62
|
"#{@name}.identified_by takes no as: — name the declared field itself"
|
|
124
63
|
end
|
|
125
|
-
# Transitional
|
|
126
|
-
# corpus still contain this form. Keep it readable until their
|
|
127
|
-
# exemplar-led migration is complete; the final lifecycle cutover
|
|
128
|
-
# replaces this assignment with the targeted refusal.
|
|
64
|
+
# Transitional: the self-hosted language and live corpus still use this form.
|
|
129
65
|
@identity_field_pending = field
|
|
130
66
|
return
|
|
131
67
|
end
|
|
@@ -141,11 +77,7 @@ module Hecks
|
|
|
141
77
|
|
|
142
78
|
private
|
|
143
79
|
|
|
144
|
-
# Resolves
|
|
145
|
-
# pending, against `identity_pool` — the includer's own private
|
|
146
|
-
# hook. Called at build time, not at `identified_by`'s own call
|
|
147
|
-
# time — see `AttributeCollector#resolve_identity_field!`'s own
|
|
148
|
-
# comment on why.
|
|
80
|
+
# Resolves the pending identity against `identity_pool` at build time, not call time.
|
|
149
81
|
def resolve_pending_identity!
|
|
150
82
|
if @identity_type_pending
|
|
151
83
|
type, as, insert_at = @identity_type_pending
|
|
@@ -162,11 +94,7 @@ module Hecks
|
|
|
162
94
|
def identity_type?(target) = target.to_s.match?(/\A[A-Z]/)
|
|
163
95
|
|
|
164
96
|
def refuse_second_identity!
|
|
165
|
-
#
|
|
166
|
-
# may be replaced by the new declaration later in the same builder.
|
|
167
|
-
# This keeps existing builder fixtures/source readable while their
|
|
168
|
-
# exemplar is migrated. Once one-symbol identity is retired this
|
|
169
|
-
# compatibility branch disappears with it.
|
|
97
|
+
# Transitional: a one-symbol declaration may still be replaced by a later one.
|
|
170
98
|
if @identity_field_pending && !@identity_type_pending && !@identity_fields_pending
|
|
171
99
|
@identity_field_pending = nil
|
|
172
100
|
return
|
|
@@ -178,10 +106,7 @@ module Hecks
|
|
|
178
106
|
raise Malformed, "#{@name} declares identified_by more than once"
|
|
179
107
|
end
|
|
180
108
|
|
|
181
|
-
#
|
|
182
|
-
# multi-line block), kept alive only for `EraGuard.shadow_parse`
|
|
183
|
-
# (S0a, ADR 0025) to still make sense of frozen era text that used
|
|
184
|
-
# them; unreachable outside `MetaValidator.shadow_parsing?`.
|
|
109
|
+
# Parses the spellings frozen era text uses, for `EraGuard.shadow_parse`.
|
|
185
110
|
def legacy_identified_by(*targets, as:, &path)
|
|
186
111
|
target = targets.first
|
|
187
112
|
if target
|
|
@@ -2,11 +2,7 @@ require_relative "word_gate"
|
|
|
2
2
|
module Hecks
|
|
3
3
|
module Bluebook
|
|
4
4
|
module DSL
|
|
5
|
-
# Parses a `lifecycle :field, default: ... do transition ... end`
|
|
6
|
-
# block into a `Lifecycle` — the field an aggregate or entity's own
|
|
7
|
-
# state machine lives on, its starting value, and the `command =>
|
|
8
|
-
# target_state` transition table (with an optional `from:` guard)
|
|
9
|
-
# each `transition_impl` call adds a row to.
|
|
5
|
+
# Parses a `lifecycle :field, default: ... do transition ... end` block into a `Lifecycle`.
|
|
10
6
|
class LifecycleBuilder
|
|
11
7
|
GRAMMAR_CONTEXT = "Lifecycle".freeze
|
|
12
8
|
|
|
@@ -22,11 +18,7 @@ module Hecks
|
|
|
22
18
|
|
|
23
19
|
# Records one transition row per command in `mapping`, all sharing its `from:` guard.
|
|
24
20
|
#
|
|
25
|
-
#
|
|
26
|
-
# through its `calls:` column — item #13's full metaprogrammed
|
|
27
|
-
# dispatch (slice 4c). Bootstrap-reachable (syntax.bluebook's
|
|
28
|
-
# own Keyword/Argument entities describe their `status`
|
|
29
|
-
# lifecycle with it), so in `BOOTSTRAP_CALLS_FALLBACK`.
|
|
21
|
+
# Listed in `BOOTSTRAP_CALLS_FALLBACK` because syntax.bluebook uses it during boot.
|
|
30
22
|
#
|
|
31
23
|
# @param mapping [Hash{String, Symbol => String, Symbol, Array<String>}] command name to
|
|
32
24
|
# target state, as in `"Purchase" => "sold"`; the optional `:from` key holds the
|
|
@@ -70,17 +62,11 @@ module Hecks
|
|
|
70
62
|
|
|
71
63
|
private
|
|
72
64
|
|
|
73
|
-
# C5.3 (docs/semantics/bluebook-semantics.md)
|
|
74
|
-
#
|
|
75
|
-
# `
|
|
76
|
-
# machine can be read whole. Two transitions for one command from
|
|
77
|
-
# disjoint states are the legitimate shape (`match_transition`
|
|
78
|
-
# picks by the current state) and stay. A `from:` naming a state
|
|
79
|
-
# nothing declares is not refused here: it is a reachability
|
|
80
|
-
# finding `bin/model_check` already reports (unreachable state,
|
|
81
|
-
# dead transition), and a bluebook may declare it on purpose.
|
|
65
|
+
# C5.3 (docs/semantics/bluebook-semantics.md): overlapping `from:` sets for one command
|
|
66
|
+
# are refused. Disjoint sets are legitimate. An undeclared `from:` state is left to
|
|
67
|
+
# `bin/model_check`.
|
|
82
68
|
def refuse_ambiguity!
|
|
83
|
-
return if MetaValidator.shadow_parsing? # frozen era text is
|
|
69
|
+
return if MetaValidator.shadow_parsing? # frozen era text is exempt
|
|
84
70
|
|
|
85
71
|
@transitions.each_with_index do |(command, transition), index|
|
|
86
72
|
earlier = @transitions[0...index].find do |other_command, other|
|
|
@@ -2,12 +2,8 @@ require_relative "word_gate"
|
|
|
2
2
|
module Hecks
|
|
3
3
|
module Bluebook
|
|
4
4
|
module DSL
|
|
5
|
-
# Parses a `policy "Name" do ... end` block into a `Policy
|
|
6
|
-
#
|
|
7
|
-
# optional `where` guard evaluated against the event's own payload, an
|
|
8
|
-
# optional `for_each` fan-out query, and the `trigger` command it
|
|
9
|
-
# dispatches (`with:` projecting the event's payload onto the
|
|
10
|
-
# command's own arguments when the two shapes differ).
|
|
5
|
+
# Parses a `policy "Name" do ... end` block into a `Policy`: the event it reacts to (`on`),
|
|
6
|
+
# an optional `where` guard, an optional `for_each` fan-out, and the `trigger` it dispatches.
|
|
11
7
|
class PolicyBuilder
|
|
12
8
|
GRAMMAR_CONTEXT = "Policy".freeze
|
|
13
9
|
|
|
@@ -20,20 +16,8 @@ module Hecks
|
|
|
20
16
|
|
|
21
17
|
# Records the event this policy reacts to.
|
|
22
18
|
#
|
|
23
|
-
# `
|
|
24
|
-
#
|
|
25
|
-
# the same way `trigger`/`dispatch` already resolve a command
|
|
26
|
-
# reference (`Naming.event_ref`, that method's own header). Not
|
|
27
|
-
# a required spelling yet, unlike `trigger`'s own quoted-text
|
|
28
|
-
# refusal — see `policy.bluebook`'s own KeywordSeed comment for
|
|
29
|
-
# why: event names aren't 100% migrated across the live corpus
|
|
30
|
-
# the way command references are, so both `on "Account.
|
|
31
|
-
# AccountFrozen"` (quoted) and `on Account::AccountFrozen`
|
|
32
|
-
# (bare) stay admitted until a full migration lands.
|
|
33
|
-
#
|
|
34
|
-
# Reached through `calls: "on_impl"` rather than `GenericDispatch`'s generic single-fill
|
|
35
|
-
# coercion, the same way `trigger_impl` below overrides its own generic default — `on`
|
|
36
|
-
# admits both a bare constant and quoted text, not one single argument kind.
|
|
19
|
+
# Reached through `calls: "on_impl"` because `on` admits both a bare constant
|
|
20
|
+
# (`on Account::AccountFrozen`) and quoted text, not one single argument kind.
|
|
37
21
|
#
|
|
38
22
|
# @param event_ref [Symbol, String, Module] the event, as a bare constant (a
|
|
39
23
|
# `ScopedConstant` module `ConstShim` resolves) or quoted text
|
|
@@ -42,45 +26,16 @@ module Hecks
|
|
|
42
26
|
@on_event = Naming.event_ref(event_ref)
|
|
43
27
|
end
|
|
44
28
|
|
|
45
|
-
# Records the command this policy dispatches and
|
|
46
|
-
# projects onto it.
|
|
47
|
-
#
|
|
48
|
-
# `with:` — what the trigger is given, when the event's own shape
|
|
49
|
-
# is not it. Omitted, the whole event payload forwards verbatim.
|
|
50
|
-
#
|
|
51
|
-
# Same `key => value` shape a saga's own `dispatch ..., with:`
|
|
52
|
-
# takes, and read the same way at runtime: a Symbol names a field
|
|
53
|
-
# on the triggering event, anything else is a literal the policy
|
|
54
|
-
# supplies itself. The reason it exists is the reason a saga's
|
|
55
|
-
# does — a reaction crosses an aggregate boundary, and the event
|
|
56
|
-
# on one side is under no obligation to be shaped like the
|
|
57
|
-
# command on the other. Without it the target has to declare
|
|
58
|
-
# every field the event happens to carry, whether it reads them
|
|
59
|
-
# or not.
|
|
60
|
-
# The command itself, not its name (ADR 0025, "events and
|
|
61
|
-
# reactions" — command references become first-class): `trigger
|
|
62
|
-
# Account::Debit`, a bare constant `ConstShim` resolves the same
|
|
63
|
-
# way `reference_to Account` always has, not a quoted verb string.
|
|
64
|
-
# Matches the qualified-or-not shape a saga's own `dispatch`
|
|
65
|
-
# command name takes — see `Naming.command_ref`'s own header for
|
|
66
|
-
# how the `::`/`.` rewrite works, and `SagaInterpreter#qualified`
|
|
67
|
-
# for why an unqualified form is always enough (same-domain is
|
|
68
|
-
# the fallback, so `Account::Debit` and `Banking::Account::Debit`
|
|
69
|
-
# mean the same thing here).
|
|
29
|
+
# Records the command this policy dispatches and how the event payload projects onto it.
|
|
70
30
|
#
|
|
71
|
-
#
|
|
72
|
-
#
|
|
31
|
+
# With `with:`, a Symbol value names a field on the triggering event and anything else is
|
|
32
|
+
# a literal. Omitted, the whole payload forwards.
|
|
33
|
+
# In `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
|
|
73
34
|
#
|
|
74
|
-
#
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
#
|
|
78
|
-
#
|
|
79
|
-
# @param command_ref [Symbol, String, Module] the command, as a bare constant (a
|
|
80
|
-
# `ScopedConstant` module `ConstShim` resolves) or, under shadow-parsing, quoted text
|
|
81
|
-
# @param with [Hash{Symbol => Object}, nil] a projection from the triggering event's payload
|
|
82
|
-
# onto the command's own arguments; a Symbol value names an event field, anything else is
|
|
83
|
-
# a literal; `nil` forwards the whole event payload verbatim
|
|
35
|
+
# @param command_ref [Symbol, String, Module] the command, as a bare constant or, under
|
|
36
|
+
# shadow-parsing, quoted text
|
|
37
|
+
# @param with [Hash{Symbol => Object}, nil] event payload to command arguments;
|
|
38
|
+
# `nil` forwards the whole payload
|
|
84
39
|
# @return [void]
|
|
85
40
|
# @raise [Bluebook::DSL::Malformed] if `command_ref` is quoted text outside shadow-parsing
|
|
86
41
|
def trigger_impl(command_ref, with: nil)
|
|
@@ -97,13 +52,8 @@ module Hecks
|
|
|
97
52
|
|
|
98
53
|
# Records the domain this policy's trigger reaches into.
|
|
99
54
|
#
|
|
100
|
-
# `
|
|
101
|
-
#
|
|
102
|
-
# target never to be reached (no such domain, on purpose), which
|
|
103
|
-
# `ModelCheck` holds it to in both directions. Reached through
|
|
104
|
-
# `calls: "across_impl"` rather than the generic single-fill
|
|
105
|
-
# coercion, because `expect_undelivered:` is a keyword argument the
|
|
106
|
-
# generic coercion cannot take.
|
|
55
|
+
# `expect_undelivered: true` declares that the target is expected never to be reached
|
|
56
|
+
# (no such domain, on purpose); `ModelCheck` holds it to that in both directions.
|
|
107
57
|
#
|
|
108
58
|
# @param domain [String, Symbol] the target domain's name
|
|
109
59
|
# @param expect_undelivered [Boolean] whether this domain expects `across`'s target to
|
|
@@ -117,20 +67,8 @@ module Hecks
|
|
|
117
67
|
# Records the guard predicate that decides whether this policy applies to a triggering
|
|
118
68
|
# event.
|
|
119
69
|
#
|
|
120
|
-
#
|
|
121
|
-
#
|
|
122
|
-
# is never called, here or at runtime — Runtime::PolicyInterpreter
|
|
123
|
-
# evaluates the extracted text through the same
|
|
124
|
-
# Bluebook::Expression::Evaluator a command's own given/ensures run
|
|
125
|
-
# through). No description argument the way given/ensures each
|
|
126
|
-
# carry one : a given's description becomes a GivenNotMet message,
|
|
127
|
-
# and a where that does not hold refuses nothing — it just means
|
|
128
|
-
# this policy does not apply to this event, exactly like an
|
|
129
|
-
# `event_qualifier` miss, which carries no message either.
|
|
130
|
-
#
|
|
131
|
-
# Evaluated against the triggering event's own payload, not a
|
|
132
|
-
# stored record — a policy reacts to what just happened, and has no
|
|
133
|
-
# aggregate instance of its own to read state from.
|
|
70
|
+
# The block's source is extracted and never called; a `where` that does not hold refuses
|
|
71
|
+
# nothing, so unlike `given` it takes no description. It sees the event's payload only.
|
|
134
72
|
#
|
|
135
73
|
# @yield the guard predicate, extracted as source text and evaluated later by
|
|
136
74
|
# `Runtime::PolicyInterpreter` against the triggering event's payload; never called here
|
|
@@ -147,22 +85,12 @@ module Hecks
|
|
|
147
85
|
"could not be read, so no other runtime could ever evaluate it"
|
|
148
86
|
end
|
|
149
87
|
|
|
150
|
-
# C3.6 — the same PatternSubset check every rule site gets.
|
|
151
88
|
ast = Expression::AstJson.emit_predicate(canonical)
|
|
152
89
|
Expression::AstJson.refuse_unshared_patterns!(ast, owner: @name, word: "where")
|
|
153
90
|
Expression::AstJson.refuse_unresolvable_lookups!(ast, owner: @name, word: "where")
|
|
154
91
|
@where = canonical
|
|
155
92
|
end
|
|
156
93
|
|
|
157
|
-
# **The fan-out source** — a query verb, "Aggregate.query_name" or
|
|
158
|
-
# "Domain::Aggregate.query_name", the same qualified-or-not shape a
|
|
159
|
-
# saga's own `dispatch` command name already takes
|
|
160
|
-
# (SagaInterpreter#qualified). Runtime::PolicyInterpreter runs the
|
|
161
|
-
# named query against the triggering event's own payload and fires
|
|
162
|
-
# `trigger` once per row, instead of once for the event.
|
|
163
|
-
# `for_each` — item #13's full metaprogrammed dispatch, slice 1:
|
|
164
|
-
# same shape as `on`, above.
|
|
165
|
-
|
|
166
94
|
# Builds the `Policy` this builder has accumulated.
|
|
167
95
|
#
|
|
168
96
|
# @return [Bluebook::Policy] the built policy, carrying every field set by `on`,
|
|
@@ -38,12 +38,8 @@ module Hecks
|
|
|
38
38
|
|
|
39
39
|
# Declares one method an adapter bound to this port must respond to.
|
|
40
40
|
#
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
# dispatch to reach it without a bare `NoMethodError`. Declared the
|
|
44
|
-
# same repeatable way `AdapterBuilder#field`/`#secret` already are,
|
|
45
|
-
# so `verify!` can check it with `respond_to?` at boot instead of
|
|
46
|
-
# the runtime discovering it live.
|
|
41
|
+
# Repeatable, like `AdapterBuilder#field`; `verify!` checks each name with `respond_to?`
|
|
42
|
+
# at boot so a dispatch never meets a bare `NoMethodError`.
|
|
47
43
|
#
|
|
48
44
|
# @param name [Symbol, String] the method name, such as `:ask`
|
|
49
45
|
# @return [Array<Symbol>] every method declared so far, this one last
|
|
@@ -2,40 +2,17 @@ require_relative "word_gate"
|
|
|
2
2
|
module Hecks
|
|
3
3
|
module Bluebook
|
|
4
4
|
module DSL
|
|
5
|
-
# Parses one `operation`/`tells`/`asks` block
|
|
6
|
-
#
|
|
7
|
-
# payload) plus either the events it `emits` (inbound) or the
|
|
8
|
-
# `answers`/`refuses` pair naming its two possible outcomes (outbound).
|
|
9
|
-
# `to:` records which aggregate the operation routes to as dispatch
|
|
10
|
-
# metadata, never as an attribute — see `to:`'s own comment below.
|
|
5
|
+
# Parses one `operation`/`tells`/`asks` block into a `PortOperation`: its attributes plus
|
|
6
|
+
# either the events it `emits` (inbound) or its `answers`/`refuses` pair (outbound).
|
|
11
7
|
class PortOperationBuilder
|
|
12
8
|
GRAMMAR_CONTEXT = "PortOperation".freeze
|
|
13
9
|
|
|
14
10
|
include AttributeCollector
|
|
15
11
|
include WordGate
|
|
16
12
|
|
|
17
|
-
# `to:`
|
|
18
|
-
#
|
|
19
|
-
#
|
|
20
|
-
# the argument DomainPort's own grammar (domain_port.bluebook)
|
|
21
|
-
# gives operation/tells/asks to receive it.
|
|
22
|
-
#
|
|
23
|
-
# **Genuine routing metadata, not an attribute** — matching
|
|
24
|
-
# rust/parser/src/parse/domain_port.rs's own header comment ("The
|
|
25
|
-
# receiving aggregate is routing metadata supplied by to:, not an
|
|
26
|
-
# operation attribute"), which anticipated this shape before either
|
|
27
|
-
# side actually built it. Stored separately (below, threaded to
|
|
28
|
-
# PortOperation as `to:`) rather than reusing reference_to_impl's
|
|
29
|
-
# own attribute-adding path — Dispatcher#port_invocation
|
|
30
|
-
# (lib/hecks/runtime/dispatcher.rb) is the one place that resolves
|
|
31
|
-
# routing at dispatch time; it gained a second, purely additive
|
|
32
|
-
# branch for this (falls back to a plain attribute named for the
|
|
33
|
-
# owning aggregate's own identified_by field, the same "declare
|
|
34
|
-
# only external facts with attribute" the refusal message
|
|
35
|
-
# describes) rather than folding `to:` into identity_attribute's
|
|
36
|
-
# existing Reference-attribute scan, which every operation already
|
|
37
|
-
# in the corpus (Banking, pizzas, a client site's own vendored
|
|
38
|
-
# PaymentGateway) still relies on unchanged.
|
|
13
|
+
# `to:` is the sanctioned replacement for `reference_to` inside an operation body —
|
|
14
|
+
# genuine routing metadata, not an attribute, resolved at dispatch time by
|
|
15
|
+
# `Dispatcher#port_invocation` rather than folded into the ordinary attribute scan.
|
|
39
16
|
#
|
|
40
17
|
# @param name [String] the operation's name
|
|
41
18
|
# @param to [Symbol, String, Module, nil] the aggregate the operation routes to; stored
|
|
@@ -50,33 +27,13 @@ module Hecks
|
|
|
50
27
|
@emits = []
|
|
51
28
|
end
|
|
52
29
|
|
|
53
|
-
# Refuses `reference_to` inside an operation body
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
#
|
|
57
|
-
# spells — a port operation has no `creates?`/`acts_on` distinction
|
|
58
|
-
# to protect, so there is nothing for the self-reference branch to be
|
|
59
|
-
# for here. `reference_to Payment, as: :payment_id` reads the same
|
|
60
|
-
# even though the target happens to equal the owning aggregate.
|
|
61
|
-
# Answers the `reference_to` word through the table's `calls:`
|
|
62
|
-
# column — item #13's full metaprogrammed dispatch (slice 4b).
|
|
63
|
-
# Bootstrap-reachable, in `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
|
|
64
|
-
#
|
|
65
|
-
# Disabled, #335 — kept only for MetaValidator's own shadow-parsing
|
|
66
|
-
# pass (the self-hosted grammar's own KeywordSeed/ArgumentSeed rows
|
|
67
|
-
# for "reference_to" in this context are themselves declared using
|
|
68
|
-
# this construct, one level up — deleting the Ruby method would
|
|
69
|
-
# break the language describing itself, not just old domain
|
|
70
|
-
# authors). Every real domain author reaches `to:` instead, above —
|
|
71
|
-
# a genuinely different mechanism now, not a relocated spelling of
|
|
72
|
-
# this one (see `to:`'s own comment).
|
|
30
|
+
# Refuses `reference_to` inside an operation body; a port operation has no self-reference
|
|
31
|
+
# to protect the way `CommandBuilder`'s does. Kept only for MetaValidator's own
|
|
32
|
+
# shadow-parsing pass, which still declares itself using this construct — every real
|
|
33
|
+
# domain author reaches `to:` instead (see its own comment above).
|
|
73
34
|
#
|
|
74
|
-
# @
|
|
75
|
-
#
|
|
76
|
-
# `:payment_id` under shadow-parsing
|
|
77
|
-
# @return [nil] nothing useful; the reference lands in `attributes`
|
|
78
|
-
# @raise [Bluebook::DSL::Malformed] always outside shadow-parsing, since routing belongs
|
|
79
|
-
# in `to:`; under shadow-parsing, if the attribute name is already declared
|
|
35
|
+
# @raise [Bluebook::DSL::Malformed] always outside shadow-parsing; under shadow-parsing,
|
|
36
|
+
# if the attribute name is already declared
|
|
80
37
|
def reference_to_impl(type, as: nil)
|
|
81
38
|
unless MetaValidator.shadow_parsing?
|
|
82
39
|
raise Malformed,
|
|
@@ -88,25 +45,14 @@ module Hecks
|
|
|
88
45
|
end
|
|
89
46
|
|
|
90
47
|
# Names one event an inbound operation records once the external fact has arrived.
|
|
91
|
-
#
|
|
92
|
-
# @param event_name [String, Symbol] the event's name, such as `"PaymentSettled"`
|
|
93
|
-
# @return [Array<String>] every event named so far, this one last
|
|
94
48
|
def emits(event_name) = @emits << event_name.to_s
|
|
95
49
|
|
|
96
|
-
#
|
|
97
|
-
#
|
|
98
|
-
#
|
|
99
|
-
# rather than two `emits` because a reader has to be able to tell them
|
|
100
|
-
# apart without reading the adapter: one is the thing you wanted, the
|
|
101
|
-
# other is the thing you have to handle.
|
|
102
|
-
# `answers`/`refuses` — item #13's full metaprogrammed dispatch,
|
|
103
|
-
# slice 1 (whole-project table-unification survey): both a bare,
|
|
104
|
-
# kind-driven coerce-and-assign with nothing else, now executed
|
|
105
|
-
# by `GenericDispatch`.
|
|
50
|
+
# `answers`/`refuses`, the two halves of an `asks` — separate words rather than two
|
|
51
|
+
# `emits` so a reader can tell what came back from what the outside refused, without
|
|
52
|
+
# reading the adapter.
|
|
106
53
|
|
|
107
54
|
# Assembles the operation, refusing words that belong to the other direction.
|
|
108
55
|
#
|
|
109
|
-
# @return [Bluebook::PortOperation] the operation with its attributes, events and routing
|
|
110
56
|
# @raise [Bluebook::DSL::Malformed] if an inbound operation declares no `emits` or
|
|
111
57
|
# declares `answers`/`refuses`, or an outbound one declares `emits` or lacks either
|
|
112
58
|
# `answers` or `refuses`
|
|
@@ -119,9 +65,8 @@ module Hecks
|
|
|
119
65
|
direction: @direction, answers: @answers, refuses: @refuses, to: @to
|
|
120
66
|
)
|
|
121
67
|
|
|
122
|
-
#
|
|
123
|
-
#
|
|
124
|
-
# `refuse_wrong_words!` above has already insisted on both.
|
|
68
|
+
# Only inbound: an `asks` says it with `answers`/`refuses` instead, already enforced
|
|
69
|
+
# above.
|
|
125
70
|
if !outbound && @emits.empty?
|
|
126
71
|
raise Malformed,
|
|
127
72
|
"#{@name} declares no emits — an operation with nothing to say " \
|
|
@@ -133,21 +78,15 @@ module Hecks
|
|
|
133
78
|
|
|
134
79
|
private
|
|
135
80
|
|
|
136
|
-
# The one
|
|
137
|
-
# `
|
|
138
|
-
# parsing branch call this, so there is exactly one real
|
|
139
|
-
# implementation of "carry a Reference-typed external fact,"
|
|
140
|
-
# not two that could drift.
|
|
81
|
+
# The one real implementation of "carry a Reference-typed external fact" — both `to:` and
|
|
82
|
+
# `reference_to_impl`'s shadow-parsing branch call this, so there is nothing to drift.
|
|
141
83
|
def add_reference!(type, as: nil)
|
|
142
84
|
target = Naming.demodulise(type)
|
|
143
85
|
attribute_impl(as || default_reference_name(target), Reference.new(target))
|
|
144
86
|
end
|
|
145
87
|
|
|
146
|
-
#
|
|
147
|
-
#
|
|
148
|
-
# nowhere. `answers` on a `tells` is worse — there is no channel back
|
|
149
|
-
# to an inbound caller at all, so it would read as a promise the
|
|
150
|
-
# runtime cannot keep.
|
|
88
|
+
# Each direction refuses the other's words: `emits` on an `asks` names one ending and
|
|
89
|
+
# leaves the other nowhere; `answers` on a `tells` promises a channel that never exists.
|
|
151
90
|
def refuse_wrong_words!(outbound)
|
|
152
91
|
if outbound
|
|
153
92
|
unless @emits.empty?
|
|
@@ -170,21 +109,8 @@ module Hecks
|
|
|
170
109
|
end
|
|
171
110
|
end
|
|
172
111
|
|
|
173
|
-
# Evaluates one operation block against a fresh builder and returns what it built
|
|
174
|
-
#
|
|
175
|
-
# `private` above (scoping the instance methods between it and here)
|
|
176
|
-
# doesn't reach a singleton method — correctly so: `.build` is this
|
|
177
|
-
# builder's real public entry point (DomainPortBuilder calls it),
|
|
178
|
-
# never meant to be private.
|
|
179
|
-
#
|
|
180
|
-
# @param name [String] the operation's name
|
|
181
|
-
# @param to [Symbol, String, Module, nil] the aggregate the operation routes to, or nil
|
|
182
|
-
# @param owner [String, nil] name of the aggregate the enclosing port is declared on
|
|
183
|
-
# @param direction [Symbol] `:inbound` for `operation`/`tells`, `:outbound` for `asks`
|
|
184
|
-
# @yield the operation body, evaluated with the builder as `self`; may be omitted
|
|
185
|
-
# @return [Bluebook::PortOperation] the built operation
|
|
186
|
-
# @raise [Bluebook::DSL::Malformed] if the body uses the other direction's words, omits
|
|
187
|
-
# the ones its own direction requires, or uses a word the grammar does not admit
|
|
112
|
+
# Evaluates one operation block against a fresh builder and returns what it built;
|
|
113
|
+
# `private` above doesn't reach this singleton method, since `.build` is the real entry.
|
|
188
114
|
# rubocop:disable-next Lint/IneffectiveAccessModifier
|
|
189
115
|
def self.build(name, to: nil, owner: nil, direction: :inbound, &block)
|
|
190
116
|
builder = new(name, to: to, owner: owner, direction: direction)
|