hecks 2.8.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 +4 -6
- 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 +17 -98
- 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 +5 -48
- 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 +31 -141
- 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 +14 -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 +25 -31
- 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 +16 -69
- 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 -194
- 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 -111
- 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 +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +43 -305
- 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 +6 -21
- data/lib/hecks/bluebook/model_check.rb +100 -597
- 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 +4 -23
- data/lib/hecks/cli/document.rb +3 -21
- data/lib/hecks/cli/ir.rb +3 -5
- data/lib/hecks/cli/mcp.rb +2 -3
- data/lib/hecks/cli/mcp_door.rb +19 -114
- data/lib/hecks/cli/model_check.rb +18 -85
- data/lib/hecks/cli/project_cli.rb +7 -40
- data/lib/hecks/cli/project_diagrams.rb +0 -7
- data/lib/hecks/cli/run.rb +12 -58
- data/lib/hecks/cli/smoke_test.rb +2 -16
- data/lib/hecks/cli/stores.rb +1 -2
- data/lib/hecks/cli.rb +18 -24
- 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 +82 -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 +9 -90
- 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 +61 -64
- 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 +6 -25
- 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 +18 -124
- 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 +150 -678
- 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 +2 -15
- 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 +42 -134
- 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 +3 -6
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/gem_publisher.rb +2 -3
- data/lib/hecks/release/runner/npm_publisher.rb +6 -20
- data/lib/hecks/release/runner/preflight.rb +4 -19
- data/lib/hecks/release/runner/tagger.rb +2 -9
- data/lib/hecks/release/runner.rb +3 -32
- 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 +124 -306
- 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 +64 -219
- 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 +117 -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 +99 -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 +141 -568
- 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.rb +26 -81
- 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 +3 -2
|
@@ -1,27 +1,11 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
module MetaValidator
|
|
4
|
-
# The leaf shapes of a reconstructed bluebook
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
# Reconstruction walks the tree; this rebuilds the small hashes at its tips —
|
|
8
|
-
# an attribute, a rule, a where-clause, a transition — and undoes the two
|
|
9
|
-
# things the walk encodes on the way in: an attribute's type offered as the ID
|
|
10
|
-
# of whatever it names, and an append flattened to one row per binding.
|
|
11
|
-
#
|
|
12
|
-
# Separate from the traversal because they are different concerns, and because
|
|
13
|
-
# the two together were 211 code lines against a 200 limit.
|
|
4
|
+
# The leaf shapes of a reconstructed bluebook: the small hashes at each tip of
|
|
5
|
+
# the tree (attribute, rule, where-clause, transition), decoded from their wire form.
|
|
14
6
|
module Shapes
|
|
15
7
|
# The type came in as the id of what it names, so it goes back out as the
|
|
16
8
|
# name — or, for another aggregate's head, as the encoding the IR spells.
|
|
17
|
-
#
|
|
18
|
-
# @param field [Hash{Symbol => Object}] one dispatched attribute row
|
|
19
|
-
# @param aggregate_id [String] the owning aggregate's own id, to
|
|
20
|
-
# strip from an owned value-object type
|
|
21
|
-
# @return [Hash{Symbol => Object}] `:name` (`Symbol`, `nil`),
|
|
22
|
-
# `:type` (`String`), `:list`/`:optional` (`Boolean`), `:default`
|
|
23
|
-
# (decoded literal, `nil` when absent), `:pattern`/`:admits`/
|
|
24
|
-
# `:relationship` (`String`, `nil` when absent)
|
|
25
9
|
def attribute(field, aggregate_id)
|
|
26
10
|
type = text(field[:type]).to_s
|
|
27
11
|
|
|
@@ -35,24 +19,16 @@ module Hecks
|
|
|
35
19
|
# bluebook that says something other than what was written.
|
|
36
20
|
optional: text(field[:optional]).to_s == "true",
|
|
37
21
|
pattern: presence(text(field[:pattern])),
|
|
38
|
-
# The round trip is the only way in
|
|
39
|
-
# assembled graph
|
|
40
|
-
#
|
|
41
|
-
# matter how plainly the .bluebook file declares it.
|
|
22
|
+
# The round trip is the only way in: the grammar registry keeps the
|
|
23
|
+
# assembled graph, so a fact dropped here is a fact no projection
|
|
24
|
+
# downstream ever sees, however plainly the .bluebook declares it.
|
|
42
25
|
admits: presence(text(field[:admits])),
|
|
43
26
|
relationship: presence(text(field[:relationship]))
|
|
44
27
|
}
|
|
45
28
|
end
|
|
46
29
|
|
|
47
|
-
# A type this aggregate owns, offered
|
|
48
|
-
#
|
|
49
|
-
# object's identity — the aggregate it belongs to, then its name.
|
|
50
|
-
#
|
|
51
|
-
# @param type [String] the attribute's own dispatched `type` cell
|
|
52
|
-
# @param aggregate_id [String] the owning aggregate's own id
|
|
53
|
-
# @return [String, nil] `type` with the owner's own identity prefix
|
|
54
|
-
# stripped, or `nil` if `type` does not carry that prefix (an
|
|
55
|
-
# ordinary type name, or a cross-aggregate reference)
|
|
30
|
+
# A type this aggregate owns, offered on the wire as its id.
|
|
31
|
+
# Read back here as the bare name, stripping the owner/identity prefix.
|
|
56
32
|
def owned_type(type, aggregate_id)
|
|
57
33
|
prefix = Naming.identity([aggregate_id, ""])
|
|
58
34
|
return nil unless type.start_with?(prefix)
|
|
@@ -60,64 +36,20 @@ module Hecks
|
|
|
60
36
|
type.delete_prefix(prefix)
|
|
61
37
|
end
|
|
62
38
|
|
|
63
|
-
# A
|
|
64
|
-
#
|
|
65
|
-
# An attribute typed with a sibling aggregate's value object or entity is offered
|
|
66
|
-
# as that declaration's id (chapter, owning aggregate, name), three segments. A
|
|
67
|
-
# `Reference<X>` is offered as the target head's id, two segments. The extra segment
|
|
68
|
-
# is what tells a type name from a reference, so a three-segment id is the bare
|
|
69
|
-
# declaration name and only a two-segment id is a reference.
|
|
70
|
-
#
|
|
71
|
-
# @param type [String] the attribute's own dispatched `type` cell
|
|
72
|
-
# @return [String, nil] the declaration's bare name when `type` is a three-segment id;
|
|
73
|
-
# `nil` for a head's two-segment id
|
|
39
|
+
# A sibling aggregate's declared type, offered as its id; read back as the bare name.
|
|
40
|
+
# A three-segment id names a declaration; a two-segment id is a Reference head instead.
|
|
74
41
|
def sibling_type(type)
|
|
75
42
|
segments = type.split(Naming::IDENTITY_JOIN)
|
|
76
43
|
segments.last if segments.size == 3
|
|
77
44
|
end
|
|
78
45
|
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
# as one table.
|
|
82
|
-
#
|
|
83
|
-
# @param part [Hash{Symbol => Object}] one dispatched identity-part row
|
|
84
|
-
# @return [String] the identity part's own path text
|
|
46
|
+
# The inverse of `Marks#identity_path`, named the same so the two
|
|
47
|
+
# directions read as one table.
|
|
85
48
|
def identity_path(part) = text(part[:value]).to_s
|
|
86
49
|
|
|
87
|
-
# An argument, a parameter, a piece's attribute —
|
|
88
|
-
#
|
|
89
|
-
#
|
|
90
|
-
# the aggregate's whole shape one level down), so its attributes name a
|
|
91
|
-
# value object exactly the way an aggregate's own do (`Judge#cell`'s own
|
|
92
|
-
# comment), and reconstruction has to undo the same owned-vs-reference
|
|
93
|
-
# split `attribute`, below, already undoes for an aggregate — not the
|
|
94
|
-
# cruder "any qualified name is a Reference" guess this used before,
|
|
95
|
-
# which mistook a piece's own value-object type for a cross-aggregate
|
|
96
|
-
# head every time.
|
|
97
|
-
#
|
|
98
|
-
# `aggregate_id`, passed only for a piece's own attribute (an
|
|
99
|
-
# argument or a parameter carries no value-object type at all — see
|
|
100
|
-
# entity.bluebook's/command.bluebook's own comments on why — so the
|
|
101
|
-
# generic reader path calls this with one argument and gets the
|
|
102
|
-
# old reading unchanged), is the piece's owning aggregate — the same
|
|
103
|
-
# one its own attribute types were resolved against on the way in
|
|
104
|
-
# (`Judge#owning_aggregate_ref`).
|
|
105
|
-
#
|
|
106
|
-
# A reference among the other two came in as the head's ID, because
|
|
107
|
-
# that is what Command/Query.Reference offer, so it goes back out as
|
|
108
|
-
# the encoding the IR spells. A qualified name is the tell : an
|
|
109
|
-
# ordinary type names something declared beside it (`Money`,
|
|
110
|
-
# `AccountNumber`) and never carries a chapter, while a head's id
|
|
111
|
-
# always does.
|
|
112
|
-
#
|
|
113
|
-
# @param field [Hash{Symbol => Object}] one dispatched attribute,
|
|
114
|
-
# argument, or parameter row
|
|
115
|
-
# @param aggregate_id [String, nil] the piece's own owning
|
|
116
|
-
# aggregate id, passed only for a piece's own attribute
|
|
117
|
-
# @return [Hash{Symbol => Object}] `:name` (`Symbol`, `nil`),
|
|
118
|
-
# `:type` (`String`), `:list`/`:optional` (`Boolean`), `:default`
|
|
119
|
-
# (decoded literal, `nil` when absent), `:pattern`/`:admits`/
|
|
120
|
-
# `:relationship` (`String`, `nil` when absent)
|
|
50
|
+
# An argument, a parameter, or (via `aggregate_id`) a piece's own attribute —
|
|
51
|
+
# a piece's own attribute names a value object exactly the way an aggregate's
|
|
52
|
+
# own does, so it takes the same owned-type reading `attribute`, above, does.
|
|
121
53
|
def shape_field(field, aggregate_id = nil)
|
|
122
54
|
return attribute(field, aggregate_id) if aggregate_id
|
|
123
55
|
|
|
@@ -125,10 +57,8 @@ module Hecks
|
|
|
125
57
|
|
|
126
58
|
{
|
|
127
59
|
name: text(field[:name])&.to_sym,
|
|
128
|
-
# A qualified name is the tell
|
|
129
|
-
#
|
|
130
|
-
# all, where a head's id always does (chapter + name, joined the way
|
|
131
|
-
# every derived id is).
|
|
60
|
+
# A qualified name is the tell: an ordinary type (`Money`, `AccountNumber`)
|
|
61
|
+
# carries no join at all, while a head's id always does (chapter + name).
|
|
132
62
|
type: type.include?(Naming::IDENTITY_JOIN) ? reference_type(type) : text(field[:type]),
|
|
133
63
|
list: text(field[:list]).to_s == "true",
|
|
134
64
|
default: decode_literal(text(field[:default])),
|
|
@@ -139,109 +69,47 @@ module Hecks
|
|
|
139
69
|
}
|
|
140
70
|
end
|
|
141
71
|
|
|
142
|
-
#
|
|
143
|
-
#
|
|
144
|
-
# is a real regex (it matches everything), so keeping it would turn
|
|
145
|
-
# "no pattern" into "a pattern that always passes" and quietly cost the
|
|
146
|
-
# IR its round trip.
|
|
147
|
-
#
|
|
148
|
-
# @param text [String, nil] a dispatched cell's own already-unwrapped
|
|
149
|
-
# text
|
|
150
|
-
# @return [String, nil] `text`, or `nil` when `text` is `nil` or
|
|
151
|
-
# empty
|
|
72
|
+
# "" is a real regex (matches everything) — kept as-is it would silently
|
|
73
|
+
# turn "no pattern" into "always matches", so it is coerced to nil here.
|
|
152
74
|
def presence(text)
|
|
153
75
|
value = text.to_s
|
|
154
76
|
value.empty? ? nil : value
|
|
155
77
|
end
|
|
156
78
|
|
|
157
|
-
#
|
|
158
|
-
#
|
|
159
|
-
# spelling. The forms are exactly the five the Primitive vocabulary admits —
|
|
160
|
-
# String, Integer, Float, TrueClass, FalseClass — plus a symbol, and an
|
|
161
|
-
# object literal, which is what `to: { value: "good" }` is: a value object's
|
|
162
|
-
# fields written inline.
|
|
163
|
-
#
|
|
164
|
-
# @param text [String, nil] the self-describing wire spelling
|
|
165
|
-
# `Readings#encode_literal` wrote
|
|
166
|
-
# @return [Object] `nil`, `true`, `false`, `Integer`, `Float`,
|
|
167
|
-
# `Symbol`, `Hecks::StateRef`, `String`, `Hash`, or `Array` — or
|
|
168
|
-
# `text` itself, stripped, when it matches no known spelling
|
|
79
|
+
# The self-describing form `Readings#encode_literal` wrote — the same
|
|
80
|
+
# reader `Assembly::Marks` uses, for the identical spelling.
|
|
169
81
|
def decode_literal(text) = Literal.read(text)
|
|
170
82
|
|
|
171
|
-
#
|
|
172
|
-
# `given`/`invariant`/`ensures`.
|
|
173
|
-
#
|
|
174
|
-
# @param row [Hash{Symbol => Object}] one dispatched rule row
|
|
175
|
-
# @return [Hash{Symbol => String}] `:description` and `:canonical`
|
|
83
|
+
# A rule's plain description/canonical pair, for a `given`/`invariant`/`ensures`.
|
|
176
84
|
def rule(row) = { description: text(row[:description]), canonical: text(row[:canonical]) }
|
|
177
85
|
|
|
178
|
-
#
|
|
179
|
-
#
|
|
180
|
-
# description/canonical as.
|
|
181
|
-
#
|
|
182
|
-
# @param row [Hash{Symbol => Object}] one dispatched projected-field
|
|
183
|
-
# row
|
|
184
|
-
# @return [Hash{Symbol => String}] `:name`, `:reference`, and
|
|
185
|
-
# `:remote_field`
|
|
86
|
+
# `projects :name, from: :"reference.remote_field"` (ADR 0025), read back as
|
|
87
|
+
# its plain name/reference/remote_field triple.
|
|
186
88
|
def projected_field(row)
|
|
187
89
|
{ name: text(row[:name]), reference: text(row[:reference]), remote_field: text(row[:remote_field]) }
|
|
188
90
|
end
|
|
189
91
|
|
|
190
|
-
# `provenance from: {...}` rides the same literal encoding `default:`
|
|
191
|
-
#
|
|
192
|
-
# level up: a whole keyword's argument rather than an attribute's
|
|
193
|
-
# `default:`.
|
|
194
|
-
#
|
|
195
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying a
|
|
196
|
-
# `:provenance` cell
|
|
197
|
-
# @return [Object] the decoded `from:` object literal, or `nil` when
|
|
198
|
-
# absent
|
|
92
|
+
# `provenance from: {...}` rides the same literal encoding `default:` does,
|
|
93
|
+
# one level up: a whole keyword's argument rather than an attribute's.
|
|
199
94
|
def provenance(row) = decode_literal(text(row[:provenance]))
|
|
200
95
|
|
|
201
|
-
# `command "Debit", from: "open"` — the same literal encoding
|
|
202
|
-
# `provenance`/`default:`
|
|
203
|
-
# state or an array of them, or nil for a command with no
|
|
204
|
-
# lifecycle guard.
|
|
205
|
-
#
|
|
206
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying a
|
|
207
|
-
# `:from` cell
|
|
208
|
-
# @return [String, Array<String>, nil] the decoded lifecycle guard
|
|
209
|
-
# state(s), or `nil` for a command with no lifecycle guard
|
|
96
|
+
# `command "Debit", from: "open"` (ADR 0025) — the same literal encoding
|
|
97
|
+
# `provenance`/`default:` ride, one state or an array of them, or nil.
|
|
210
98
|
def from(row) = decode_literal(text(row[:from]))
|
|
211
99
|
|
|
212
|
-
# A flag
|
|
213
|
-
# `Policy#expect_undelivered` on the wire.
|
|
214
|
-
#
|
|
215
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying an
|
|
216
|
-
# `:expect_undelivered` cell
|
|
217
|
-
# @return [Boolean] whether the flag reads `"true"`
|
|
100
|
+
# A flag held as text ("true"/"false"), emitted as a boolean.
|
|
218
101
|
def expect_undelivered?(row) = text(row[:expect_undelivered]).to_s == "true"
|
|
219
102
|
|
|
220
|
-
#
|
|
221
|
-
#
|
|
222
|
-
# One row per part, so a compound option is several rows and a repeated one is
|
|
223
|
-
# several groups told apart by `at`. Grouping by option name and then by `at`
|
|
224
|
-
# rebuilds both without either knowing which options exist — the whole point
|
|
225
|
-
# of holding them as an open map.
|
|
226
|
-
#
|
|
227
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying an
|
|
228
|
-
# `:options` list
|
|
229
|
-
# @return [Hash{Symbol => Object}] one entry per option name; each
|
|
230
|
-
# value is `gathered`'s own return for that option's own parts
|
|
103
|
+
# Regroups dispatched option rows into the shape `extra_options_to_h` spells:
|
|
104
|
+
# one row per part, several `at`-keyed groups for a repeated option.
|
|
231
105
|
def options_of(row)
|
|
232
106
|
Array(row[:options])
|
|
233
107
|
.group_by { |part| text(part[:option]) }
|
|
234
108
|
.to_h { |option, parts| [option.to_sym, gathered(parts)] }
|
|
235
109
|
end
|
|
236
110
|
|
|
237
|
-
#
|
|
238
|
-
#
|
|
239
|
-
#
|
|
240
|
-
# @param parts [Array<Hash{Symbol => Object}>] one option's own
|
|
241
|
-
# dispatched key/value/at rows
|
|
242
|
-
# @return [Hash{Symbol => String}, Array<Hash{Symbol => String}>]
|
|
243
|
-
# a single `key => value` hash when no part carries `at`;
|
|
244
|
-
# otherwise an array of such hashes, one per distinct `at`
|
|
111
|
+
# One option's own parts, grouped back into a single binding — or several
|
|
112
|
+
# `at`-keyed groups when the option repeats.
|
|
245
113
|
def gathered(parts)
|
|
246
114
|
repeated, single = parts.partition { |part| !text(part[:at]).to_s.empty? }
|
|
247
115
|
return single.to_h { |part| [text(part[:key]).to_sym, text(part[:value])] } if repeated.empty?
|
|
@@ -251,29 +119,14 @@ module Hecks
|
|
|
251
119
|
.map { |group| group.to_h { |part| [text(part[:key]).to_sym, text(part[:value])] } }
|
|
252
120
|
end
|
|
253
121
|
|
|
254
|
-
#
|
|
255
|
-
#
|
|
256
|
-
#
|
|
257
|
-
# from (via `read`), and decoding twice is worse than once — a
|
|
258
|
-
# kwarg reference (":ceiling") decoded here into the Symbol :ceiling
|
|
259
|
-
# would have its colon stripped by `read`'s own `.to_s` and come
|
|
260
|
-
# back out as the plain string "ceiling", indistinguishable from a
|
|
261
|
-
# literal of the same name. One decode, at the one place that builds
|
|
262
|
-
# the object every comparator actually reads.
|
|
263
|
-
#
|
|
264
|
-
# @param row [Hash{Symbol => Object}] one dispatched where-clause row
|
|
265
|
-
# @return [Hash{Symbol => String}] `:field`, `:op`, and `:value`
|
|
266
|
-
# (raw text, undecoded)
|
|
122
|
+
# Kept as raw text, not decoded: this feeds `Assembly::Marks#where_clause`,
|
|
123
|
+
# which decodes it via `read` — decoding here first would strip a kwarg
|
|
124
|
+
# reference's colon, indistinguishable after from a same-named literal.
|
|
267
125
|
def where_clause(row)
|
|
268
126
|
{ field: text(row[:field]), op: text(row[:op]), value: text(row[:value]) }
|
|
269
127
|
end
|
|
270
128
|
|
|
271
129
|
# One object in the IR, two fields in the language.
|
|
272
|
-
#
|
|
273
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying
|
|
274
|
-
# `:order_field`/`:order_way` cells
|
|
275
|
-
# @return [Hash{Symbol => String}, nil] `:field` and `:direction`,
|
|
276
|
-
# or `nil` when no `order_field` was declared
|
|
277
130
|
def order_by(row)
|
|
278
131
|
field = text(row[:order_field])
|
|
279
132
|
return nil if field.to_s.empty?
|
|
@@ -281,12 +134,7 @@ module Hecks
|
|
|
281
134
|
{ field: field, direction: text(row[:order_way]) }
|
|
282
135
|
end
|
|
283
136
|
|
|
284
|
-
#
|
|
285
|
-
#
|
|
286
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying a
|
|
287
|
-
# `:limit` cell
|
|
288
|
-
# @return [Hash{Symbol => String}, nil] `{value: ceiling}`, or `nil`
|
|
289
|
-
# when no limit was declared
|
|
137
|
+
# A read model's own declared row limit, or nil when none was declared.
|
|
290
138
|
def limit(row)
|
|
291
139
|
ceiling = text(row[:limit])
|
|
292
140
|
return nil if ceiling.to_s.empty?
|
|
@@ -294,12 +142,6 @@ module Hecks
|
|
|
294
142
|
{ value: ceiling }
|
|
295
143
|
end
|
|
296
144
|
|
|
297
|
-
# Reads one lifecycle transition row.
|
|
298
|
-
#
|
|
299
|
-
# @param row [Hash{Symbol => Object}] one dispatched lifecycle
|
|
300
|
-
# transition row
|
|
301
|
-
# @return [Hash{Symbol => String}] `:command`, `:from_state`, and
|
|
302
|
-
# `:to_state`
|
|
303
145
|
def transition(row)
|
|
304
146
|
{
|
|
305
147
|
command: text(row[:command]),
|
|
@@ -308,83 +150,38 @@ module Hecks
|
|
|
308
150
|
}
|
|
309
151
|
end
|
|
310
152
|
|
|
311
|
-
# Reads one reference head — a process manager handler's own
|
|
312
|
-
# aggregate binding.
|
|
313
|
-
#
|
|
314
|
-
# @param row [Hash{Symbol => Object}] one dispatched reference-head
|
|
315
|
-
# row
|
|
316
|
-
# @return [Hash{Symbol => Object}] `:aggregate`/`:as` (`String`) and
|
|
317
|
-
# `:many` (`Boolean`)
|
|
318
153
|
def head(row)
|
|
319
154
|
{
|
|
320
155
|
aggregate: text(row[:aggregate]),
|
|
321
|
-
# A String, like an entity's identified_by. The IR is not uniform
|
|
322
|
-
# this and only a round trip says so.
|
|
156
|
+
# A String, like an entity's identified_by. The IR is not uniform
|
|
157
|
+
# about this and only a round trip says so.
|
|
323
158
|
as: text(row[:as]),
|
|
324
159
|
many: text(row[:many]).to_s == "true"
|
|
325
160
|
}
|
|
326
161
|
end
|
|
327
162
|
|
|
328
|
-
# Reads a read model's own `group_by` field name.
|
|
329
|
-
#
|
|
330
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying a
|
|
331
|
-
# `:field` cell
|
|
332
|
-
# @return [Hash{Symbol => String}] `{field: ...}`
|
|
333
163
|
def group_by_field(row) = { field: text(row[:field]) }
|
|
334
164
|
|
|
335
|
-
# `
|
|
336
|
-
#
|
|
337
|
-
# `ReadModel.Count` command is dispatched at all only when
|
|
338
|
-
# `@count` was truthy (`MetaValidator::Judge#setters` skips a
|
|
339
|
-
# setter whose every source is absent), so an undeclared read
|
|
340
|
-
# model's own `count` field never gets written and comes back
|
|
341
|
-
# `nil` here, never `"false"` — matching `ReadModel#to_h`'s own
|
|
342
|
-
# `true`/`nil` pair (never `false`) exactly, rather than the
|
|
343
|
-
# unconditional `true`/`false` `head`'s own `many` needs (every
|
|
344
|
-
# head does get a `Gather` dispatch, declared or derived).
|
|
345
|
-
#
|
|
346
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying a
|
|
347
|
-
# `:count` cell
|
|
348
|
-
# @return [Boolean, nil] `true` when the flag reads `"true"`, `nil`
|
|
349
|
-
# for an undeclared read model's own `count`
|
|
165
|
+
# Mirrors `head`'s own `many`, but nil (never `false`) for an undeclared
|
|
166
|
+
# read model — matching `ReadModel#to_h`'s own true/nil pairing.
|
|
350
167
|
def read_model_count(row) = (true if text(row[:count]).to_s == "true")
|
|
351
168
|
|
|
352
|
-
#
|
|
353
|
-
#
|
|
354
|
-
#
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
#
|
|
358
|
-
#
|
|
359
|
-
# @param row [Hash{Symbol => Object}] a dispatched row carrying a
|
|
360
|
-
# `:mutations` list
|
|
361
|
-
# @return [Array<Hash{Symbol => Object}>] one hash per distinct
|
|
362
|
-
# `target`/`op` pair, each `mutation`'s own return
|
|
169
|
+
# `percentile_at` is stored as text (the self-hosted grammar's own
|
|
170
|
+
# `ReadModelText`, ADR 0078), but the wire and `ReadModel#initialize`'s
|
|
171
|
+
# own `&.to_f` both want a Float.
|
|
172
|
+
def read_model_percentile_at(row) = text(row[:percentile_at])&.to_f
|
|
173
|
+
|
|
174
|
+
# The append flattening, in reverse: regroups per-binding rows back
|
|
175
|
+
# into one mutation per distinct target/op pair.
|
|
363
176
|
def mutations(row)
|
|
364
177
|
Array(row[:mutations])
|
|
365
178
|
.group_by { |change| [text(change[:target]), text(change[:op])] }
|
|
366
179
|
.map { |(target, op), bindings| mutation(target, op, bindings) }
|
|
367
180
|
end
|
|
368
181
|
|
|
369
|
-
# `sign:`
|
|
370
|
-
#
|
|
371
|
-
#
|
|
372
|
-
# meta-domain's own Change entity carries no `sign` field of its
|
|
373
|
-
# own (it is a pure function of `op`, nothing to persist), so
|
|
374
|
-
# reconstruction recomputes it the same way a freshly-built
|
|
375
|
-
# Mutation's own `to_h` lambda does, rather than leaving the key
|
|
376
|
-
# silently absent (spec/round_trip_spec's whole point: a field the
|
|
377
|
-
# language does not hold is a named gap, not a byte-for-byte one).
|
|
378
|
-
#
|
|
379
|
-
# @param target [String] the mutated field's own name
|
|
380
|
-
# @param oper [String] the mutation's operation name, such as
|
|
381
|
-
# `"set"`, `"append"`, `"delegate"`, or `"corrects"`
|
|
382
|
-
# @param bindings [Array<Hash{Symbol => Object}>] this target/op
|
|
383
|
-
# pair's own dispatched binding rows
|
|
384
|
-
# @return [Hash{Symbol => Object}] `:target`/`:op` (`Symbol`),
|
|
385
|
-
# `:sign` (`String`), plus `:fields` (`appended`'s own return) for
|
|
386
|
-
# `"append"`/`"delegate"`/`"corrects"`, or `:source`
|
|
387
|
-
# (`classified`'s own return) for anything else
|
|
182
|
+
# `sign:` is recomputed via `Mutation.sign_for`, not stored on any row —
|
|
183
|
+
# Change carries no `sign` field of its own, so a fresh Mutation's `to_h`
|
|
184
|
+
# derives it the same way here, rather than leaving the key silently absent.
|
|
388
185
|
def mutation(target, oper, bindings)
|
|
389
186
|
base = { target: target.to_sym, op: oper.to_sym, sign: Hecks::Bluebook::Mutation.sign_for(oper) }
|
|
390
187
|
# `:delegate`/`:corrects` (CommandBuilder#delegates_to's and
|
|
@@ -395,24 +192,13 @@ module Hecks
|
|
|
395
192
|
base.merge(source: classified(bindings.first))
|
|
396
193
|
end
|
|
397
194
|
|
|
398
|
-
# Rebuilds an append's own field -> source map from its flattened
|
|
399
|
-
# per-binding rows.
|
|
400
|
-
#
|
|
401
|
-
# @param bindings [Array<Hash{Symbol => Object}>] one append's own
|
|
402
|
-
# dispatched binding rows
|
|
403
|
-
# @return [Hash{Symbol => String}] each bound field name mapped to
|
|
404
|
-
# its own source text
|
|
195
|
+
# Rebuilds an append's own field -> source map from its flattened per-binding rows.
|
|
405
196
|
def appended(bindings)
|
|
406
197
|
bindings.to_h { |binding| [text(binding[:field]).to_sym, text(binding[:source])] }
|
|
407
198
|
end
|
|
408
199
|
|
|
409
|
-
# Classifies a single-binding mutation's own source
|
|
410
|
-
#
|
|
411
|
-
# @param binding [Hash{Symbol => Object}] one dispatched binding row
|
|
412
|
-
# @return [Hash{Symbol => Object}] `{kind: "argument"|"state",
|
|
413
|
-
# name: String}` for an argument or state reference, or
|
|
414
|
-
# `{kind: "literal", value: Object}` (the decoded literal) for
|
|
415
|
-
# anything else
|
|
200
|
+
# Classifies a single-binding mutation's own source: argument/state
|
|
201
|
+
# reference, or a decoded literal.
|
|
416
202
|
def classified(binding)
|
|
417
203
|
kind = text(binding[:kind])
|
|
418
204
|
value = text(binding[:source])
|