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
|
@@ -3,15 +3,8 @@ require_relative "aggregate_builder/sealing"
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Bluebook
|
|
5
5
|
module DSL
|
|
6
|
-
# The `aggregate "Name" do ... end` receiver
|
|
7
|
-
#
|
|
8
|
-
# (attributes, value objects, entities, commands, queries, policies,
|
|
9
|
-
# invariants, preconditions, projected fields, its lifecycle and
|
|
10
|
-
# identity) and assembling the final `Aggregate` IR in `#build`.
|
|
11
|
-
# `entity`/`command`/`query` only queue a descriptor during
|
|
12
|
-
# `instance_eval` (`#drain_pending!` builds them, in order, once the
|
|
13
|
-
# whole block has run) so a later-declared piece can still be
|
|
14
|
-
# referenced by an earlier line — see `#drain_pending!`'s own header.
|
|
6
|
+
# The `aggregate "Name" do ... end` receiver: collects an aggregate's attributes,
|
|
7
|
+
# entities, commands, queries, policies and rules, and assembles the `Aggregate` IR.
|
|
15
8
|
class AggregateBuilder
|
|
16
9
|
GRAMMAR_CONTEXT = "Aggregate".freeze
|
|
17
10
|
|
|
@@ -43,33 +36,18 @@ module Hecks
|
|
|
43
36
|
@queries = []
|
|
44
37
|
@policies = []
|
|
45
38
|
@reference_targets = []
|
|
46
|
-
#
|
|
47
|
-
# comment. One hash for the whole aggregate, threaded unchanged
|
|
48
|
-
# into every piece nested under it, however deep.
|
|
39
|
+
# Shared unchanged with every entity/command this aggregate builds (see `#entity_impl`).
|
|
49
40
|
@entity_named_givens = {}
|
|
50
|
-
#
|
|
51
|
-
# from `BluebookBuilder#aggregate`, shared with every other
|
|
52
|
-
# aggregate the same chapter builds. See `#given`'s own
|
|
53
|
-
# comment for what this closes.
|
|
41
|
+
# Threaded in from `BluebookBuilder#aggregate`; shared chapter-wide across aggregates.
|
|
54
42
|
@chapter_named_givens = chapter_named_givens
|
|
55
|
-
#
|
|
56
|
-
# way as `@chapter_named_givens`, one Array shared chapter-wide.
|
|
57
|
-
# See `#pending_chapter_given`'s own comment for what queues
|
|
58
|
-
# here and `BluebookBuilder#resolve_pending_chapter_givens!`
|
|
59
|
-
# for where it drains.
|
|
43
|
+
# Threaded chapter-wide; a chapter may span multiple files (see `#pending_chapter_given`)
|
|
60
44
|
@chapter_pending_givens = chapter_pending_givens
|
|
61
|
-
# One level wider
|
|
62
|
-
#
|
|
63
|
-
# `BluebookBuilder#aggregate_impl` the same way
|
|
64
|
-
# `@chapter_named_givens` is, and passed straight through
|
|
65
|
-
# (unchanged) to every top-level piece this aggregate builds
|
|
66
|
-
# (`#drain_pending!`). See `EntityBuilder#given_impl`'s own
|
|
67
|
-
# comment for what this closes.
|
|
45
|
+
# One level wider than `@chapter_named_givens`: the chapter's entity-scoped pool,
|
|
46
|
+
# passed through unchanged to every entity this aggregate builds.
|
|
68
47
|
@chapter_entity_named_givens = chapter_entity_named_givens
|
|
69
48
|
@chapter_entity_pending_givens = chapter_entity_pending_givens
|
|
70
|
-
#
|
|
71
|
-
#
|
|
72
|
-
# `#drain_pending!`'s own comment for why.
|
|
49
|
+
# `entity`/`command`/`query` queue a descriptor here instead of building eagerly
|
|
50
|
+
# (see `#drain_pending!`).
|
|
73
51
|
@pending_entities = []
|
|
74
52
|
@pending_commands = []
|
|
75
53
|
@pending_queries = []
|
|
@@ -80,28 +58,11 @@ module Hecks
|
|
|
80
58
|
# @param value [String] the description text
|
|
81
59
|
# @return [String] the description as stored
|
|
82
60
|
def description(value)
|
|
83
|
-
# moved to the language: Description invariant, on Root.Declare
|
|
84
|
-
|
|
85
61
|
@description = value
|
|
86
62
|
end
|
|
87
63
|
|
|
88
64
|
# Names where a concept adopted from a canonical source came from.
|
|
89
65
|
#
|
|
90
|
-
# Origin, not runtime identity — a concept adopted from a canonical
|
|
91
|
-
# source (§28) names where it came from without that fact ever
|
|
92
|
-
# touching `hecks_fqn`/dispatch. Captured raw, the same way
|
|
93
|
-
# `attribute ..., default: { value: "small" }` captures a literal
|
|
94
|
-
# Hash untouched — no re-parsing, no structure imposed beyond
|
|
95
|
-
# "whatever the author wrote."
|
|
96
|
-
#
|
|
97
|
-
# Answers the `provenance` word (and, via the same table rows,
|
|
98
|
-
# its siblings `projects`/`lifecycle`/`entity`/
|
|
99
|
-
# `query`/`policy`/`command` below) through the table's `calls:`
|
|
100
|
-
# column — item #13's full
|
|
101
|
-
# metaprogrammed dispatch (slice 4c). All bootstrap-reachable
|
|
102
|
-
# (used throughout the core/attached chapters), all in
|
|
103
|
-
# `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
|
|
104
|
-
#
|
|
105
66
|
# @param from [Object] the canonical source, captured exactly as written
|
|
106
67
|
# @return [Object] `from` as stored
|
|
107
68
|
def provenance_impl(from:)
|
|
@@ -110,24 +71,6 @@ module Hecks
|
|
|
110
71
|
|
|
111
72
|
# Declares a reference from this aggregate's own head to another aggregate's identity.
|
|
112
73
|
#
|
|
113
|
-
# `optional:` — matching `CommandBuilder#reference_to`'s own
|
|
114
|
-
# signature, which already had it, and forwarded here to
|
|
115
|
-
# `attribute_impl()`/`relationship_attribute` (`optional: optional`, below). A real
|
|
116
|
-
# need: an aggregate that can point at one
|
|
117
|
-
# of several targets (Item's own `personal_list_id`/
|
|
118
|
-
# `camping_list_id`, never both) needs each reference optional
|
|
119
|
-
# on the aggregate's own persisted schema, not just as a
|
|
120
|
-
# command's input — real corpus use:
|
|
121
|
-
# `spec/fixtures/hop_chain.bluebook`'s own `Proposal` aggregate
|
|
122
|
-
# declares `reference_to Engagement, optional: true` at the
|
|
123
|
-
# aggregate head.
|
|
124
|
-
#
|
|
125
|
-
# Answers the `reference_to` word through the table's `calls:`
|
|
126
|
-
# column — item #13's full metaprogrammed
|
|
127
|
-
# dispatch (slice 4b). Bootstrap-reachable (every core/attached
|
|
128
|
-
# grammar chapter uses reference_to to describe itself), so also
|
|
129
|
-
# named in `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
|
|
130
|
-
#
|
|
131
74
|
# @param type [Module, Symbol, String] the referenced aggregate, written as a bare
|
|
132
75
|
# constant
|
|
133
76
|
# @param as [Symbol, nil] the attribute's name; nil derives it from `type`
|
|
@@ -144,34 +87,10 @@ module Hecks
|
|
|
144
87
|
# Declares that this aggregate holds its own kept-fresh copy of a field reached through
|
|
145
88
|
# a reference, so a rule can read it locally instead of reaching across the boundary.
|
|
146
89
|
#
|
|
147
|
-
#
|
|
148
|
-
#
|
|
149
|
-
# `reference_to` at rule-evaluation time (`References#
|
|
150
|
-
# dereference`, a live query against another aggregate's own
|
|
151
|
-
# repository) would be unbounded and inconsistent with the "a rule reads
|
|
152
|
-
# only this record" model everywhere else — `projects` is what
|
|
153
|
-
# replaces that: `projects :customer_status, from: :"customer.
|
|
154
|
-
# status"` declares that this aggregate holds its own copy of
|
|
155
|
-
# `Customer`'s own `:status`, kept fresh by a rebuild sweep
|
|
156
|
-
# (`Runtime::ProjectionRebuild`) rather than read live. A rule
|
|
157
|
-
# then reads `customer_status` the same way it reads any other
|
|
158
|
-
# local field — no dot, no reference walk.
|
|
159
|
-
#
|
|
160
|
-
# `from:` names the local reference, not the target aggregate —
|
|
161
|
-
# `customer`, the attribute this aggregate's own `reference_to
|
|
162
|
-
# Customer` already minted, not `Customer` the type — so two
|
|
163
|
-
# references to the same aggregate (aliased differently) can
|
|
164
|
-
# each carry their own projection without ambiguity. The target
|
|
165
|
-
# field's own existence cannot be checked here: the target
|
|
166
|
-
# aggregate does not exist yet while this one is still being
|
|
167
|
-
# declared (the same reason a query's own hop tail is checked
|
|
168
|
-
# by `BluebookBuilder#validate_query_hops!`, once every
|
|
169
|
-
# aggregate in the chapter is real, not by `AggregateBuilder`
|
|
170
|
-
# itself) — `validate_projected_fields!` is where that half
|
|
171
|
-
# happens.
|
|
90
|
+
# `from:` names the local reference, not the target aggregate, so two references to the
|
|
91
|
+
# same aggregate can each carry their own projection.
|
|
172
92
|
#
|
|
173
|
-
# @param name [Symbol, String] the local field
|
|
174
|
-
# remote value into
|
|
93
|
+
# @param name [Symbol, String] the local field receiving the projected remote value
|
|
175
94
|
# @param from [Symbol, String] the local reference and remote field, dotted, such as
|
|
176
95
|
# `:"customer.status"`
|
|
177
96
|
# @return [Array<Bluebook::ProjectedField>] every projected field declared so far, this
|
|
@@ -191,41 +110,18 @@ module Hecks
|
|
|
191
110
|
remote_field: remote_field.to_sym)
|
|
192
111
|
end
|
|
193
112
|
|
|
194
|
-
# `has_many`/`has_one`/`belongs_to` were legacy (ADR 0025,
|
|
195
|
-
# "References") — sugar over `reference_to` that collapsed to an
|
|
196
|
-
# anonymous reference and, for `has_many`, lied (singularised its
|
|
197
|
-
# target and minted one scalar, so `film.backers` read `nil` and
|
|
198
|
-
# never `[]`). Wave 6 (identity-and-relationships arc) un-deprecates
|
|
199
|
-
# all three for real: a relationship word now retains the author's
|
|
200
|
-
# domain concept in IR — still stored as one or more target
|
|
201
|
-
# identities, but no longer collapsed to a bare `reference_to`
|
|
202
|
-
# during assembly. `MetaValidator.shadow_parsing?` still routes to
|
|
203
|
-
# `legacy_has_many`/`legacy_has_one` so frozen era text written
|
|
204
|
-
# under the old (lying/collapsing) meaning still parses the way it
|
|
205
|
-
# did when it was written — real, if rare corpus: "Combined corpus
|
|
206
|
-
# uses: one."
|
|
207
|
-
#
|
|
208
113
|
# Declares a list-typed relationship to another aggregate, referenced by its plural name.
|
|
209
114
|
#
|
|
210
|
-
#
|
|
211
|
-
#
|
|
212
|
-
# `calls:` column — item #13's full metaprogrammed dispatch
|
|
213
|
-
# (slice 4). Each Keyword row's own `calls:` names the matching
|
|
214
|
-
# `_impl`, so all three are carried in
|
|
215
|
-
# `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK` like every other
|
|
216
|
-
# `calls:`-routed word, but never actually exercised during real
|
|
217
|
-
# bootstrap (no core/attached chapter uses one of these to
|
|
218
|
-
# describe itself), unlike `attribute`/`role`.
|
|
115
|
+
# Under `MetaValidator.shadow_parsing?`, routes to the collapsing single-reference
|
|
116
|
+
# form instead, so frozen era text keeps its original meaning.
|
|
219
117
|
#
|
|
220
|
-
# @param type [Module, Symbol, String] the related aggregate's plural name, a bare
|
|
221
|
-
# constant
|
|
118
|
+
# @param type [Module, Symbol, String] the related aggregate's plural name, a bare constant
|
|
222
119
|
# @param as [Symbol, nil] the attribute's name; nil derives it from `type`
|
|
223
120
|
# @param legacy_options [Hash] must be empty outside shadow-parsing; under
|
|
224
121
|
# shadow-parsing, `:optional` is read for the legacy single-reference form
|
|
225
122
|
# @return [void]
|
|
226
|
-
# @raise [Bluebook::DSL::Malformed] outside shadow-parsing, if
|
|
227
|
-
#
|
|
228
|
-
# already declared
|
|
123
|
+
# @raise [Bluebook::DSL::Malformed] outside shadow-parsing, if non-empty, or if the
|
|
124
|
+
# derived name is already declared
|
|
229
125
|
def has_many_impl(type, as: nil, **legacy_options)
|
|
230
126
|
return legacy_has_many(type, as: as, optional: legacy_options.fetch(:optional, false)) if MetaValidator.shadow_parsing?
|
|
231
127
|
|
|
@@ -284,28 +180,6 @@ module Hecks
|
|
|
284
180
|
|
|
285
181
|
# Queues a piece nested in this aggregate, built later once every sibling has been seen.
|
|
286
182
|
#
|
|
287
|
-
# A piece is declared in this aggregate — its owner is stamped by
|
|
288
|
-
# `Aggregate#initialize`, once the aggregate exists. Its own
|
|
289
|
-
# commands were given the piece as their owner when it was declared,
|
|
290
|
-
# so the chain closes as chapter -> aggregate -> entity -> command.
|
|
291
|
-
# Not built here — see `#drain_pending!`'s own comment for why
|
|
292
|
-
# this only queues a descriptor.
|
|
293
|
-
#
|
|
294
|
-
# A precondition shared across sibling pieces, declared once — one
|
|
295
|
-
# level wider than round 4's own `EntityBuilder#given` (shared
|
|
296
|
-
# across one piece's own commands): `@entity_named_givens` is the
|
|
297
|
-
# same hash threaded into every piece this aggregate builds, so a
|
|
298
|
-
# piece's own entity-level `given(desc) { block }` write-throughs
|
|
299
|
-
# into it, and any other piece's own command can reference it back
|
|
300
|
-
# bare, the identical description/canonical, evaluated in its own
|
|
301
|
-
# `parent`-relative context. Real, live corpus this closes:
|
|
302
|
-
# `SafeDepositBox`'s `Visit`/`KeyIssuance` — two different pieces
|
|
303
|
-
# under one head, each independently typing `given("customer is
|
|
304
|
-
# active") { parent.customer.status == "active" }` byte for byte,
|
|
305
|
-
# which neither the aggregate's own "customer is active" (a
|
|
306
|
-
# different canonical — bare `customer.status`, not
|
|
307
|
-
# `parent.customer.status`, wrong scope for a piece's own command
|
|
308
|
-
# to evaluate) nor round 4's single-piece `given` could reach.
|
|
309
183
|
# @param name [String] the nested piece's name
|
|
310
184
|
# @yield the piece body, evaluated against an `EntityBuilder` once drained
|
|
311
185
|
# @return [Array<Array>] every pending piece queued so far, this one last
|
|
@@ -334,53 +208,14 @@ module Hecks
|
|
|
334
208
|
@policies << reaction
|
|
335
209
|
end
|
|
336
210
|
|
|
337
|
-
# Declares a value object
|
|
338
|
-
#
|
|
339
|
-
#
|
|
340
|
-
# `builder.closed_sets` too, not only `builder.build` — a real
|
|
341
|
-
# gap this exact fix closes: a
|
|
342
|
-
# value_object's own inline `attribute :x, one_of(...)` (legal
|
|
343
|
-
# since S3, ADR 0025 removed the wrong-arity collision that would
|
|
344
|
-
# otherwise crash it) synthesises its own
|
|
345
|
-
# anonymous value object via the same `AttributeCollector#closed_
|
|
346
|
-
# sets` mechanism an aggregate's own attributes already use — and
|
|
347
|
-
# nothing installed it anywhere. `Box.attributes` said `size:
|
|
348
|
-
# "Size"` while no "Size" value object existed in the whole
|
|
349
|
-
# domain: a dangling type name, not a working closed set. Flattened
|
|
350
|
-
# into this aggregate's own `@value_objects`, the identical move
|
|
351
|
-
# `@value_objects + closed_sets` already makes for the aggregate's
|
|
352
|
-
# own direct attributes (see this file's other 5 call sites).
|
|
353
|
-
# `type` — the bare shorthand (single-attribute value objects):
|
|
354
|
-
# `value_object :Price, Integer` declares a value object with
|
|
355
|
-
# exactly one attribute, named `value`, of that type — pure sugar
|
|
356
|
-
# for `value_object("Price") { attribute :value, Integer }`,
|
|
357
|
-
# routed through the same `attribute_impl` the block form's own
|
|
358
|
-
# `attribute` line reaches (so the quoted-text-type refusal,
|
|
359
|
-
# `one_of(...)`/`list_of(...)` synthesis, everything an attribute
|
|
360
|
-
# line already does, applies unchanged rather than being
|
|
361
|
-
# re-derived here). The name `value` is not arbitrary: a
|
|
362
|
-
# single-attribute value object is a name for a scalar, not a
|
|
363
|
-
# genuine group ([[feedback_name_the_scalar_field]], `Behaviour::
|
|
364
|
-
# ValueObject#sole_attribute`), and `value` is what the language
|
|
365
|
-
# guarantees every sole field answers to at runtime regardless of
|
|
366
|
-
# its declared name (`Runtime::Value#method_missing`'s alias) —
|
|
367
|
-
# so the shorthand simply declares it under the canonical name
|
|
368
|
-
# directly. Type and block together are refused: the block exists
|
|
369
|
-
# to say what the fields are, and the type just said it — two
|
|
370
|
-
# answers to one question is an authoring error, never a merge.
|
|
371
|
-
# Neither type nor block keeps its historical behavior untouched
|
|
372
|
-
# (an empty attribute list — judged, or not, by the language
|
|
373
|
-
# downstream, the same as before this parameter existed).
|
|
211
|
+
# Declares a value object: a block of `attribute` lines, or (the `type` shorthand) a
|
|
212
|
+
# single `:value` attribute.
|
|
374
213
|
#
|
|
375
214
|
# @param name [String] the value object's name
|
|
376
|
-
# @param type [Module, nil] the bare shorthand's
|
|
377
|
-
#
|
|
378
|
-
# @
|
|
379
|
-
#
|
|
380
|
-
# @return [Array<Bluebook::ValueObject>] this aggregate's own value objects, including
|
|
381
|
-
# this one and any closed sets its attributes synthesised
|
|
382
|
-
# @raise [Bluebook::DSL::Malformed] if both `type` and a block are given, or the body
|
|
383
|
-
# fails any check the value object language or its builder raises
|
|
215
|
+
# @param type [Module, nil] the bare shorthand's attribute type; exclusive with `block`
|
|
216
|
+
# @yield the `attribute`/`invariant`/`one_of` body; exclusive with `type`
|
|
217
|
+
# @return [Array<Bluebook::ValueObject>] this one, plus any closed sets synthesised
|
|
218
|
+
# @raise [Bluebook::DSL::Malformed] if both `type` and a block are given, or the body fails
|
|
384
219
|
def value_object(name, type = nil, &block)
|
|
385
220
|
if type && block
|
|
386
221
|
raise Malformed,
|
|
@@ -399,15 +234,8 @@ module Hecks
|
|
|
399
234
|
# Queues a command declared on this aggregate, built later once every sibling has been
|
|
400
235
|
# seen.
|
|
401
236
|
#
|
|
402
|
-
# `from:`
|
|
403
|
-
#
|
|
404
|
-
# ("account is open") { status == "open" }`, written 35 times
|
|
405
|
-
# in two wordings across the corpus. Checked against this
|
|
406
|
-
# aggregate's own lifecycle field (`Admissibility#enforce_
|
|
407
|
-
# lifecycle_guard`) — never a target state, never a transition:
|
|
408
|
-
# the lifecycle already declares which states exist, so naming
|
|
409
|
-
# the legal ones is checkable against it, where a free-text
|
|
410
|
-
# given could drift out of sync with the state machine and did.
|
|
237
|
+
# `from:` is checked against this aggregate's own lifecycle field, never a target
|
|
238
|
+
# state or transition, so a guard can't drift out of sync with the state machine.
|
|
411
239
|
#
|
|
412
240
|
# @param name [String] the command's name
|
|
413
241
|
# @param from [String, Symbol, Array<String, Symbol>, nil] the lifecycle state(s) this
|
|
@@ -415,108 +243,37 @@ module Hecks
|
|
|
415
243
|
# @yield the command body, evaluated against a `CommandBuilder` once drained
|
|
416
244
|
# @return [Array<Array>] every pending command queued so far, this one last
|
|
417
245
|
def command_impl(name, from: nil, &block)
|
|
418
|
-
#
|
|
419
|
-
#
|
|
420
|
-
# exists. An entity's commands take the entity as their owner instead,
|
|
421
|
-
# at the entity's own declaration. Not built here — see
|
|
422
|
-
# `#drain_pending!`'s own comment for why this only queues a
|
|
423
|
-
# descriptor.
|
|
246
|
+
# Owner is stamped once `Aggregate#initialize` runs; an entity's own commands are
|
|
247
|
+
# owned by the entity instead.
|
|
424
248
|
@pending_commands << [name, from, block]
|
|
425
249
|
end
|
|
426
250
|
|
|
427
|
-
# Declares a rule this aggregate's own commands must satisfy, or references
|
|
428
|
-
#
|
|
429
|
-
#
|
|
430
|
-
# A precondition shared across commands, declared once (S10, ADR
|
|
431
|
-
# 0025) — an aggregate-level `given`, block required, stored by
|
|
432
|
-
# its own description rather than appended anywhere: a command
|
|
433
|
-
# names it back (`given("customer is active")`, no block of its
|
|
434
|
-
# own) rather than re-typing the predicate, so there is one
|
|
435
|
-
# description and therefore one refusal message no matter which
|
|
436
|
-
# command a caller hits. Declare before the commands that
|
|
437
|
-
# reference it — resolution happens at the referencing command's
|
|
438
|
-
# own build time (`CommandBuilder#given`), against whatever this
|
|
439
|
-
# aggregate has declared so far, the one ordering constraint this
|
|
440
|
-
# word carries that `identified_by`/`attribute` do not.
|
|
441
|
-
# Bare — no block — references a sibling aggregate's own
|
|
442
|
-
# already-declared precondition, one level wider than the
|
|
443
|
-
# existing bare-command-references-its-own-aggregate shape
|
|
444
|
-
# (`CommandBuilder#reference_named_given`): `SafeDepositBox`/
|
|
445
|
-
# `OnboardingCase` both name back `Account`'s own "customer is
|
|
446
|
-
# active" rather than retyping `customer.status == "active"` a
|
|
447
|
-
# third and fourth time. Resolved against `@chapter_named_givens`
|
|
448
|
-
# — see `BluebookBuilder#aggregate`'s own comment for how that
|
|
449
|
-
# pool is threaded, and `docs/implemented/resolution-rules/chapter-given.md`
|
|
450
|
-
# for the full algorithm and its known limitations (a bare
|
|
451
|
-
# reference trusts its own author to have verified the same
|
|
452
|
-
# canonical predicate applies — this mechanism does not, and
|
|
453
|
-
# cannot, check that itself; see that doc for which real corpus
|
|
454
|
-
# cases do and do not qualify).
|
|
251
|
+
# Declares a rule this aggregate's own commands must satisfy, or references a sibling's.
|
|
252
|
+
# `declared_by:` disambiguates a bare reference when two aggregates share a description.
|
|
455
253
|
#
|
|
456
|
-
#
|
|
457
|
-
#
|
|
458
|
-
#
|
|
459
|
-
# `customer.status` (a direct `reference_to Customer`); `ATMCard`'s
|
|
460
|
-
# own (shared onward with `CardPayment`/`ExternalTransfer`/
|
|
461
|
-
# `ScheduledPayment`/`Statement`) reads `account.customer.status`
|
|
462
|
-
# (reached through `Account`) — the identical business fact, a
|
|
463
|
-
# genuinely different runtime path, correctly kept as the same
|
|
464
|
-
# domain wording rather than invented a second spelling for "the
|
|
465
|
-
# same idea, one more hop away" (S10, ADR 0025's own "one idea,
|
|
466
|
-
# one spelling"). Omit it when the description is unambiguous
|
|
467
|
-
# chapter-wide (the common case, and the only case this took
|
|
468
|
-
# before this parameter existed) — required only once a second,
|
|
469
|
-
# textually-different canonical registers under the same
|
|
470
|
-
# description; see `reference_named_chapter_given`'s own
|
|
471
|
-
# ambiguity error for how that surfaces.
|
|
472
|
-
# Answers the `given` word through the table's `calls:` column —
|
|
473
|
-
# item #13's full metaprogrammed dispatch
|
|
474
|
-
# (slice 4b), same reasoning as `reference_to_impl` above:
|
|
475
|
-
# bootstrap-reachable, in `GenericDispatch::BOOTSTRAP_CALLS_FALLBACK`.
|
|
476
|
-
#
|
|
477
|
-
# @param description [String] the rule's description; also the name a sibling aggregate
|
|
478
|
-
# references it by when no block is given
|
|
479
|
-
# @param declared_by [Module, Symbol, String, nil] disambiguates which aggregate's own
|
|
480
|
-
# rule to reference, a bare constant, when more than one shares `description`; only
|
|
481
|
-
# meaningful with no block
|
|
254
|
+
# @param description [String] the rule's description; also its name for a sibling reference
|
|
255
|
+
# @param declared_by [Module, Symbol, String, nil] which aggregate's rule; only meaningful
|
|
256
|
+
# with no block
|
|
482
257
|
# @yield the predicate body; evaluated for its extracted source, never called directly
|
|
483
258
|
# @return [void]
|
|
484
|
-
# @raise [Bluebook::DSL::Malformed] if
|
|
485
|
-
#
|
|
486
|
-
# already-loaded aggregate with no `declared_by` to disambiguate; an unresolved
|
|
487
|
-
# reference defers instead, and may still raise once the whole chapter has loaded, if
|
|
488
|
-
# it then resolves to none or more than one candidate
|
|
259
|
+
# @raise [Bluebook::DSL::Malformed] if the source can't be extracted, or a bare reference
|
|
260
|
+
# resolves to none or more than one candidate once the chapter has loaded
|
|
489
261
|
def given_impl(description, declared_by: nil, &predicate)
|
|
490
262
|
return reference_named_chapter_given(description, declared_by: declared_by) unless predicate
|
|
491
263
|
|
|
492
264
|
named = build_rule(Given, description, predicate, owner_name: @name, word: "given",
|
|
493
265
|
extraction_failure: "its source could not be read, so no other runtime could ever evaluate it")
|
|
494
266
|
@named_givens[description] = named
|
|
495
|
-
#
|
|
496
|
-
#
|
|
497
|
-
# alone: two different aggregates independently declaring the
|
|
498
|
-
# same description are two distinct candidates a later bare
|
|
499
|
-
# reference chooses between (via `declared_by:` once there is
|
|
500
|
-
# more than one), never silently merged into one slot the way
|
|
501
|
-
# a bare description-only key would.
|
|
267
|
+
# Keyed by [description, this aggregate's name] so two aggregates sharing a
|
|
268
|
+
# description are distinct candidates, never merged into one slot.
|
|
502
269
|
@chapter_named_givens[description] ||= {}
|
|
503
270
|
@chapter_named_givens[description][@name] ||= named
|
|
504
271
|
end
|
|
505
272
|
|
|
506
273
|
private
|
|
507
274
|
|
|
508
|
-
#
|
|
509
|
-
#
|
|
510
|
-
# below (exact owner / unambiguous single candidate / ambiguous)
|
|
511
|
-
# are this construct's own refusal wording, not shared, since
|
|
512
|
-
# `declared_by:` only exists here so far. Unresolved (no
|
|
513
|
-
# candidate yet, or `declared_by:` naming an aggregate that
|
|
514
|
-
# hasn't declared it yet) is no longer a fourth branch that
|
|
515
|
-
# raises here — see `#pending_chapter_given`, below, for why:
|
|
516
|
-
# a chapter split across files can genuinely reference a
|
|
517
|
-
# precondition a later file declares, and "not found among
|
|
518
|
-
# what's loaded so far" cannot tell that apart from "genuinely
|
|
519
|
-
# never declared" until every file has.
|
|
275
|
+
# Unresolved (no candidate yet) doesn't raise here — a chapter split across files
|
|
276
|
+
# may still declare this precondition in a later file (see `#pending_chapter_given`).
|
|
520
277
|
def reference_named_chapter_given(description, declared_by:)
|
|
521
278
|
verify_resolves_via!("given", "Aggregate", "owner_keyed")
|
|
522
279
|
candidates = resolve_owner_keyed(@chapter_named_givens, description)
|
|
@@ -540,34 +297,9 @@ module Hecks
|
|
|
540
297
|
@named_givens[description] = named
|
|
541
298
|
end
|
|
542
299
|
|
|
543
|
-
#
|
|
544
|
-
#
|
|
545
|
-
#
|
|
546
|
-
# once the whole chapter is assembled rather than refused the
|
|
547
|
-
# moment one file's own bare reference outruns what's loaded so
|
|
548
|
-
# far (`BluebookBuilder.validate_assembled!`'s own comment).
|
|
549
|
-
#
|
|
550
|
-
# Unlike those, though, a chapter-given's resolved value is not
|
|
551
|
-
# a pass/fail check on an already-built IR — it is part of the
|
|
552
|
-
# referencing aggregate's own IR (`preconditions:` below), built
|
|
553
|
-
# and handed off the moment this aggregate's own file finishes
|
|
554
|
-
# loading, long before a later file might declare the real
|
|
555
|
-
# thing. So this hands back a placeholder `Given` — embedded
|
|
556
|
-
# exactly where the resolved one would be, by Ruby object
|
|
557
|
-
# reference, in this aggregate's own `preconditions` and in any
|
|
558
|
-
# command in this same aggregate that separately bare-references
|
|
559
|
-
# the same description (`CommandBuilder#given`'s own hash-chain
|
|
560
|
-
# read of this aggregate's `@named_givens`, the identical key) —
|
|
561
|
-
# and queues the request in `@chapter_pending_givens`.
|
|
562
|
-
# `BluebookBuilder#resolve_pending_chapter_givens!` mutates this
|
|
563
|
-
# exact object in place, once every file has loaded, so every
|
|
564
|
-
# existing reference to it (there is only ever the one object,
|
|
565
|
-
# never a copy) sees the resolved fields simultaneously. Safe
|
|
566
|
-
# because every real reader of a `Given` — refusal wording at
|
|
567
|
-
# dispatch, `Aggregate`'s own lazy `-> { preconditions.map { ... } }`
|
|
568
|
-
# IR accessor, docs — runs strictly after boot completes, never
|
|
569
|
-
# mid-load; `judge_deferred!` resolves every pending chapter-given
|
|
570
|
-
# before anything else touches this chapter's assembled IR.
|
|
300
|
+
# Returns a placeholder `Given`, embedded by reference in this aggregate's IR;
|
|
301
|
+
# `BluebookBuilder#resolve_pending_chapter_givens!` mutates it in place once the
|
|
302
|
+
# whole chapter loads, so every existing reference sees the resolved fields together.
|
|
571
303
|
def pending_chapter_given(description, declared_by:)
|
|
572
304
|
placeholder = Given.new(description: description, canonical: nil, predicate: nil)
|
|
573
305
|
@chapter_pending_givens << { aggregate: @name, description: description,
|
|
@@ -580,19 +312,6 @@ module Hecks
|
|
|
580
312
|
# Declares a rule the whole aggregate must satisfy, checked after every command, before
|
|
581
313
|
# save.
|
|
582
314
|
#
|
|
583
|
-
# The aggregate boundary is what an invariant defines (S10, ADR
|
|
584
|
-
# 0025 — "Rules") — the same check a value object's already gets
|
|
585
|
-
# (`ValueObjectBuilder#invariant`, whose own shape this mirrors
|
|
586
|
-
# exactly). Without an aggregate-level rule, "the balance
|
|
587
|
-
# never goes negative" was three different `given`/`ensures`
|
|
588
|
-
# texts across banking's six balance-moving commands, and the
|
|
589
|
-
# four that only increase it said nothing at all — completeness
|
|
590
|
-
# depended on someone noticing which commands could decrease it.
|
|
591
|
-
#
|
|
592
|
-
# Answers the `invariant` word through the table's `calls:`
|
|
593
|
-
# column — item #13's full metaprogrammed
|
|
594
|
-
# dispatch (slice 4b), same reasoning as `given_impl` above.
|
|
595
|
-
#
|
|
596
315
|
# @param description [String] the rule's description
|
|
597
316
|
# @yield the predicate body; evaluated for its extracted source, never called directly
|
|
598
317
|
# @return [void]
|
|
@@ -638,24 +357,15 @@ module Hecks
|
|
|
638
357
|
provenance: @provenance
|
|
639
358
|
)
|
|
640
359
|
|
|
641
|
-
#
|
|
642
|
-
#
|
|
643
|
-
# builder.
|
|
360
|
+
# On purpose, after the IR exists: the object the IR graph should know is `ir`,
|
|
361
|
+
# not this builder.
|
|
644
362
|
stamp_references(ir)
|
|
645
363
|
ir
|
|
646
364
|
end
|
|
647
365
|
|
|
648
366
|
# Evaluates an `aggregate` block against a fresh builder and returns the built aggregate.
|
|
367
|
+
# The `chapter_*` params thread the chapter-wide and entity-scoped given pools through.
|
|
649
368
|
#
|
|
650
|
-
# @param name [String] the aggregate's name
|
|
651
|
-
# @param chapter_named_givens [Hash{String => Hash{String => Bluebook::Given}}] the
|
|
652
|
-
# chapter-wide given pool
|
|
653
|
-
# @param chapter_pending_givens [Array<Hash>] unresolved chapter-wide bare given
|
|
654
|
-
# references
|
|
655
|
-
# @param chapter_entity_named_givens [Hash{String => Hash{String => Bluebook::Given}}]
|
|
656
|
-
# the chapter-wide, entity-scoped given pool
|
|
657
|
-
# @param chapter_entity_pending_givens [Array<Hash>] unresolved chapter-wide,
|
|
658
|
-
# entity-scoped bare given references
|
|
659
369
|
# @yield the aggregate body, evaluated with the builder as `self`; may be omitted
|
|
660
370
|
# @return [Bluebook::Aggregate] the built aggregate
|
|
661
371
|
# @raise [Bluebook::DSL::Malformed] if the body fails any check `#build` raises
|
|
@@ -670,43 +380,9 @@ module Hecks
|
|
|
670
380
|
|
|
671
381
|
private
|
|
672
382
|
|
|
673
|
-
# Deferred
|
|
674
|
-
#
|
|
675
|
-
#
|
|
676
|
-
# :field` importing the owner's own attribute, `given("desc")`
|
|
677
|
-
# referencing an aggregate-level precondition, a query's own
|
|
678
|
-
# positional-param resolution) only ever saw whatever `@entities`/
|
|
679
|
-
# `attributes`/`@named_givens`/`@value_objects` held as of that
|
|
680
|
-
# exact textual line — never what the aggregate's block would go
|
|
681
|
-
# on to declare after it. Three real, confirmed cases in the
|
|
682
|
-
# self-hosted meta-domain violate the "declare before you
|
|
683
|
-
# reference" convention every other resolution rule relies on
|
|
684
|
-
# (`command "Handler"` before `entity "Handler"`, same for
|
|
685
|
-
# Member/Dispatch — see docs/resolution-rules/
|
|
686
|
-
# implicit-append-fields.md's own "Known limitations").
|
|
687
|
-
#
|
|
688
|
-
# This is the same move `BluebookBuilder` already makes one level
|
|
689
|
-
# up, at the chapter level — build every aggregate first, then run
|
|
690
|
-
# cross-referential validation (`validate_query_hops!`,
|
|
691
|
-
# `validate_projected_fields!`, `validate_no_bidirectional_
|
|
692
|
-
# references!`) once `@aggregates` is fully populated — extended
|
|
693
|
-
# one level down: `entity`/`command`/`query` now only queue a
|
|
694
|
-
# descriptor (`@pending_entities`/`@pending_commands`/
|
|
695
|
-
# `@pending_queries`, each preserving its own declared order),
|
|
696
|
-
# and `#build` drains them here, in this exact order, before any
|
|
697
|
-
# of the existing `seal_*` validations (which already assume
|
|
698
|
-
# `@commands`/`@entities`/`@queries` are the real, final, built
|
|
699
|
-
# objects) — entities first and fully, since a command's own
|
|
700
|
-
# `sets :list, append: {...}` needs a list's element entity
|
|
701
|
-
# already built (`.attributes` populated) to resolve against, not
|
|
702
|
-
# just named.
|
|
703
|
-
#
|
|
704
|
-
# `attribute`/`value_object`/`identified_by`/`given` (block form)
|
|
705
|
-
# are not deferred — they still build eagerly during
|
|
706
|
-
# `instance_eval`, unchanged. Nothing reads `@entities`/
|
|
707
|
-
# `@commands`/`@queries` from anywhere other than `#build` and its
|
|
708
|
-
# own private helpers (checked directly), so nothing else in this
|
|
709
|
-
# file needed to change for this to be safe.
|
|
383
|
+
# Deferred: entity/command/query queue a descriptor instead of building eagerly, so a
|
|
384
|
+
# later-declared piece can still be referenced from an earlier line. Entities drain
|
|
385
|
+
# first and fully — a command's own `sets` may need an entity's attributes already built.
|
|
710
386
|
def drain_pending!
|
|
711
387
|
@entities = @pending_entities.map do |name, block|
|
|
712
388
|
EntityBuilder.build(name, owner_value_objects: @value_objects + closed_sets,
|
|
@@ -730,10 +406,8 @@ module Hecks
|
|
|
730
406
|
end
|
|
731
407
|
end
|
|
732
408
|
|
|
733
|
-
# `identified_by`'s
|
|
734
|
-
#
|
|
735
|
-
# field's own value-object type against everything it declares
|
|
736
|
-
# itself, own inline closed sets included.
|
|
409
|
+
# `identified_by`'s resolution pool: an aggregate resolves a bare field's value-object
|
|
410
|
+
# type against its own attributes and inline closed sets.
|
|
737
411
|
def identity_pool = @value_objects + closed_sets
|
|
738
412
|
|
|
739
413
|
def identity_value_object_name = "#{Naming.demodulise(@name)}Identity"
|
|
@@ -742,8 +416,7 @@ module Hecks
|
|
|
742
416
|
@value_objects << value_object
|
|
743
417
|
end
|
|
744
418
|
|
|
745
|
-
#
|
|
746
|
-
# byte-identical to what those three did before this slice.
|
|
419
|
+
# Shadow-parsing's collapsing behavior for has_many/has_one/belongs_to.
|
|
747
420
|
def legacy_has_many(type, as:, optional: false)
|
|
748
421
|
plural = Naming.demodulise(type)
|
|
749
422
|
reference_to_impl(Naming.singularize(plural), as: as || Naming.snake(plural).to_sym, optional: optional)
|