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,211 +3,34 @@ require_relative "bootstrap_table"
|
|
|
3
3
|
module Hecks
|
|
4
4
|
module Bluebook
|
|
5
5
|
module DSL
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
# already shipped) only checks a word's admissibility; this module
|
|
9
|
-
# executes the safe, mechanical subset of what a word actually
|
|
10
|
-
# does, read live off the same self-hosted grammar table — so a
|
|
11
|
-
# builder method for one of these words no longer needs to be
|
|
12
|
-
# hand-written at all. Called from `WordGate#method_missing`'s own
|
|
13
|
-
# "admitted here, no builder method for it yet" branch, so it only
|
|
14
|
-
# ever sees a word whose (context, word) pair the grammar already
|
|
15
|
-
# admits.
|
|
16
|
-
#
|
|
17
|
-
# ## What is covered
|
|
18
|
-
#
|
|
19
|
-
# Scope, deliberately narrow and verified word-by-word — a full
|
|
20
|
-
# audit read every real Ruby builder method's own source before
|
|
21
|
-
# any of this was written, not inferred from the table's shape
|
|
22
|
-
# alone (which fooled a first pass: `ReadModelBuilder#group_by`/
|
|
23
|
-
# `#include` look like plain fills from `kind`/`fills` alone, but
|
|
24
|
-
# actually wrap their arguments in a Hash/tuple). What's covered:
|
|
25
|
-
#
|
|
26
|
-
# - a single, non-variadic, positional Argument row whose value
|
|
27
|
-
# is stored with nothing beyond a uniform, kind-driven
|
|
28
|
-
# coercion (`COERCE_BY_KIND`) — or, for `kind: "text"`, no
|
|
29
|
-
# coercion at all when the row's own `coerce: "false"` says so
|
|
30
|
-
# (six real, audited exceptions: `.to_s` on an actual String
|
|
31
|
-
# is a same-object no-op for every real corpus use, but a
|
|
32
|
-
# genuine behavior change for a direct Ruby API call passing
|
|
33
|
-
# something else)
|
|
34
|
-
# - a scalar assign (`@ivar = value`) or list append (`@ivar <<
|
|
35
|
-
# value`), chosen by whether the ivar `fills:` names is
|
|
36
|
-
# already an Array at call time (every candidate's own
|
|
37
|
-
# `initialize` pre-populates its accumulating ivars as `[]` —
|
|
38
|
-
# read live, not assumed)
|
|
39
|
-
# - a zero-argument word, either (a) one of several sibling
|
|
40
|
-
# Keyword rows in the same context sharing the same `fills:`
|
|
41
|
-
# target — derives its own stored value from its own word
|
|
42
|
-
# name as a symbol (`core`/`generic`/`supporting` all fill
|
|
43
|
-
# `classification`), or (b) the only Keyword row filling its
|
|
44
|
-
# own `fills:` target — a bare marker, stores literal `true`
|
|
45
|
-
# (`ReadModel#count`)
|
|
46
|
-
# - an OPENS_BLOCK word named in `SAFE_OPENS_BLOCK` below,
|
|
47
|
-
# verified to do nothing beyond "build the child, instance_
|
|
48
|
-
# eval the block against it, append the result" — see that
|
|
49
|
-
# constant's own comment
|
|
50
|
-
# - (slice 2) a single-fill word whose row also names a `blank_
|
|
51
|
-
# message:` — raises that exact Malformed text if the coerced
|
|
52
|
-
# value is blank, before storing it, matching a real hand-
|
|
53
|
-
# written guard exactly (`Translation#retired`/
|
|
54
|
-
# `TranslationAggregate#drop`, the only two words in the whole
|
|
55
|
-
# grammar with this precise shape — `required: "true"` alone
|
|
56
|
-
# only gates Ruby's own arity, never a present-but-blank
|
|
57
|
-
# value, and most `required: "true"` words do not raise on
|
|
58
|
-
# blank, so this needed a real per-row signal, not an
|
|
59
|
-
# assumption from `required:` alone)
|
|
60
|
-
#
|
|
61
|
-
# ## What stays hand-written
|
|
62
|
-
#
|
|
63
|
-
# Explicitly out of this slice (found live, during the audit, not
|
|
64
|
-
# assumed) — stays hand-written, unaffected, until a later slice's
|
|
65
|
-
# own new table columns (`gated_by:`/`calls:`) can name
|
|
66
|
-
# what it really does: variadic accumulation with a real transform
|
|
67
|
-
# (`attaches_to`); source-block extraction (`ensures`, `where`);
|
|
68
|
-
# Struct/Hash-wrapping (`limit`, `group_by`, `rekey`); a guard
|
|
69
|
-
# clause not reducible to a plain blank-check (`role`'s own "raise
|
|
70
|
-
# if already set" uniqueness gate — a genuinely different shape
|
|
71
|
-
# from `retired`/`drop`'s own blank-check, needing its own
|
|
72
|
-
# design); a dynamically-built refusal message rather than one
|
|
73
|
-
# fixed string (`TranslationAggregateBuilder#unresolved` — real
|
|
74
|
-
# branching logic choosing between several message shapes, not a
|
|
75
|
-
# simple "always refuses" flag; belongs with `calls:`, slice 4,
|
|
76
|
-
# where a table row can name the real Ruby helper that already
|
|
77
|
-
# builds it); a side effect beyond storage (`uses_framework`,
|
|
78
|
-
# `uses_embryonaut_bluebook`); an opens-block word threading extra
|
|
79
|
-
# constructor args to its child (`asks`/`tells`/`operation`,
|
|
80
|
-
# `Bluebook#aggregate`, `Translation#aggregate`) or doing anything
|
|
81
|
-
# beyond a bare fold after building (`Aggregate#policy`'s stamp,
|
|
82
|
-
# `Aggregate#value_object`'s flatten, `Hecksagon#port`'s resolver-
|
|
83
|
-
# swap-and-branch); the deferred-build queue pattern (`Aggregate`/
|
|
84
|
-
# `Entity`'s own `command`/`entity`/`query`); the shadow_parsing?-
|
|
85
|
-
# gated words (`has_many`/`has_one`/`belongs_to`/`then_set`/
|
|
86
|
-
# `trigger`/`dispatch`/`one_of` — each delegates to its own
|
|
87
|
-
# `legacy_*` method under `MetaValidator.shadow_parsing?`, else
|
|
88
|
-
# refuses; a genuinely different two-branch shape per word, closer
|
|
89
|
-
# to `calls:`'s own territory than a simple fill); and every
|
|
90
|
-
# `File`-context word (routes through `Runtime.current_registry`,
|
|
91
|
-
# a side effect this module has no business performing).
|
|
92
|
-
#
|
|
93
|
-
# ## Words that look table-safe and are not
|
|
94
|
-
#
|
|
95
|
-
# Two further, different reasons a word can look table-safe and
|
|
96
|
-
# still be excluded, both found live rather than assumed:
|
|
97
|
-
# - Bootstrap reachability. `WordGate`'s own gate steps aside
|
|
98
|
-
# entirely while `MetaValidator.bootstrapping?` (the meta-
|
|
99
|
-
# domain's own circularity — its grammar table doesn't exist
|
|
100
|
-
# yet to read), and `load_grammar_into` loads real `.port`/
|
|
101
|
-
# `.adapter` files, plus every core `.bluebook` chapter, during
|
|
102
|
-
# that exact window. Any word those files actually call (found
|
|
103
|
-
# to be nearly every common one — `vision`/`core`/`generic`/
|
|
104
|
-
# `supporting`/`description`/`goal`/`emits`/`role`/`identified_
|
|
105
|
-
# by` describe literally every self-hosted aggregate/command)
|
|
106
|
-
# has no working method to fall back on if its hand-written
|
|
107
|
-
# `def` is removed — `super` from `WordGate#method_missing`
|
|
108
|
-
# just raises `NoMethodError`. `PortBuilder`/`AdapterBuilder`/
|
|
109
|
-
# `BluebookBuilder` turned out to be entirely off-limits to
|
|
110
|
-
# this slice for exactly this reason, confirmed by cold-
|
|
111
|
-
# booting `MetaValidator.grammar_registry` after each
|
|
112
|
-
# candidate removal, not assumed safe from reading the table
|
|
113
|
-
# alone.
|
|
114
|
-
# - A conflicting hand-written `method_missing`. `WorldBuilder`
|
|
115
|
-
# and `HecksagonBuilder` each define their own `method_missing`
|
|
116
|
-
# directly on the class (for genuinely open-ended settings/
|
|
117
|
-
# collector verbs) — a method defined directly on a class always
|
|
118
|
-
# wins over one from an included module in Ruby's own method
|
|
119
|
-
# resolution, so `WordGate`'s (and this module's) own
|
|
120
|
-
# `method_missing` never runs for their builders at all. Their
|
|
121
|
-
# own candidate words (`realm`/`latest`, `subscribe`) stay
|
|
122
|
-
# hand-written for this structural reason, independent of
|
|
123
|
-
# whether their own behavior would otherwise qualify.
|
|
6
|
+
# Executes a grammar-admitted (context, word) pair straight off the DSL's own table when
|
|
7
|
+
# its row matches one of a few verified-safe shapes; anything else falls through unchanged.
|
|
124
8
|
module GenericDispatch
|
|
125
9
|
NOT_HANDLED = Object.new.freeze
|
|
126
10
|
|
|
127
11
|
COERCE_BY_KIND = { "text" => :to_s, "symbol" => :to_sym }.freeze
|
|
128
12
|
|
|
129
|
-
# (
|
|
130
|
-
#
|
|
131
|
-
# appending it — see this file's own header for the full account
|
|
132
|
-
# of what was excluded and why. Value: the ivar the built child
|
|
133
|
-
# is appended into. Not derivable from `fills:` — every one of
|
|
134
|
-
# these Keyword rows carries `fills: ""`; the append target is
|
|
135
|
-
# implicit in the hand-written code today, never named by the
|
|
136
|
-
# table at all, so this is the one place slice 1 hand-names a
|
|
137
|
-
# fact the table doesn't yet carry, rather than guessing a
|
|
138
|
-
# pluralization rule that would silently mismatch a future word.
|
|
13
|
+
# Not derivable from `fills:` (these rows all carry `fills: ""`) — the append target
|
|
14
|
+
# for each opens-block word must be named here explicitly.
|
|
139
15
|
SAFE_OPENS_BLOCK = {
|
|
140
16
|
%w[Bluebook policy] => :policies,
|
|
141
17
|
%w[Bluebook process_manager] => :process_managers,
|
|
142
18
|
%w[Bluebook read_model] => :read_models
|
|
143
19
|
}.freeze
|
|
144
20
|
|
|
145
|
-
# `
|
|
146
|
-
#
|
|
147
|
-
# table doesn't exist yet to read `keyword[:calls]` from). Names
|
|
148
|
-
# the same (context, word) -> method pairs the real table's own
|
|
149
|
-
# `calls:` column carries — every live row, projected ahead of
|
|
150
|
-
# time into the committed lib/hecks/bluebook/dsl/bootstrap_table.rb
|
|
151
|
-
# (bin/project_bootstrap_table, pinned by spec/bootstrap_table_spec.rb).
|
|
152
|
-
#
|
|
153
|
-
# Every row is carried, rather than a hand-kept subset checked for
|
|
154
|
-
# bootstrap-reachability by grepping the core chapters. Carrying
|
|
155
|
-
# all of them costs nothing: a builder with its own `def` never
|
|
156
|
-
# reaches `method_missing`, and one without gains the same dispatch
|
|
157
|
-
# it gets once bootstrapping ends. `["Type", word]` rows still cover
|
|
158
|
-
# `list_of`/`one_of` in an attribute's type position for every
|
|
159
|
-
# calling context (see `word_gate_dispatch`'s own header).
|
|
21
|
+
# Consulted only while `MetaValidator.bootstrapping?`, before the real grammar table
|
|
22
|
+
# exists to read `calls:` from; every row is carried since carrying them costs nothing.
|
|
160
23
|
BOOTSTRAP_CALLS_FALLBACK = BootstrapTable::CALLS
|
|
161
24
|
|
|
162
25
|
module_function
|
|
163
26
|
|
|
164
|
-
#
|
|
165
|
-
#
|
|
166
|
-
# **The static predicate** — does this (context, word) pair fall
|
|
167
|
-
# within this slice's own verified scope, without executing
|
|
168
|
-
# anything? The same row-shape checks `try` itself runs before
|
|
169
|
-
# ever touching a real argument, shared so a conformance spec
|
|
170
|
-
# (which has no real call, no real builder instance) can ask the
|
|
171
|
-
# same question `method_missing` answers live.
|
|
172
|
-
#
|
|
173
|
-
# @param context [String] the grammar context, a builder's `GRAMMAR_CONTEXT` such as
|
|
174
|
-
# `"Aggregate"`, or `"Type"`
|
|
175
|
-
# @param word [String] the DSL word; a Symbol never matches a row
|
|
176
|
-
# @param rows [Hash{Symbol => Array<Hash{Symbol => String}>}] the grammar table, with
|
|
177
|
-
# `:keywords` and `:arguments` row lists; defaults to the live self-hosted table
|
|
178
|
-
# @return [Boolean] true when `try` would execute the word rather than answer `NOT_HANDLED`
|
|
27
|
+
# Whether `try` would execute this (context, word) pair, without executing anything.
|
|
179
28
|
def handles?(context, word, rows: MetaValidator::SyntaxBoot.call)
|
|
180
29
|
!shape_for(context, word, rows).nil?
|
|
181
30
|
end
|
|
182
31
|
|
|
183
|
-
# Executes a
|
|
184
|
-
# the
|
|
185
|
-
#
|
|
186
|
-
# `NOT_HANDLED` for anything outside this slice's own verified
|
|
187
|
-
# scope — the caller (`WordGate#method_missing`) falls through
|
|
188
|
-
# to its own existing "not yet implemented" refusal, unchanged,
|
|
189
|
-
# the exact same message a word not yet migrated to any slice
|
|
190
|
-
# already gets today. A real `ArgumentError` — matching what a
|
|
191
|
-
# hand-written method of the same arity would raise — for a
|
|
192
|
-
# call whose shape the grammar admits but whose actual argument
|
|
193
|
-
# count doesn't match; never a silent wrong answer.
|
|
194
|
-
#
|
|
195
|
-
# @param builder [Bluebook::DSL::WordGate] the builder instance the word was called on
|
|
196
|
-
# @param context [String] the grammar context the word was admitted under
|
|
197
|
-
# @param word [String] the DSL word being executed
|
|
198
|
-
# @param args [Array<Object>] the call's positional arguments
|
|
199
|
-
# @param kwargs [Hash{Symbol => Object}] the call's keyword arguments
|
|
200
|
-
# @param block [Proc, nil] the block given to the word, if any
|
|
201
|
-
# @param rows [Hash{Symbol => Array<Hash{Symbol => String}>}] the grammar table, with
|
|
202
|
-
# `:keywords` and `:arguments` row lists
|
|
203
|
-
# @return [Object] what executing the word produced — the target method's own result
|
|
204
|
-
# for a `calls:` row, otherwise the stored value or the list appended to — or
|
|
205
|
-
# `NOT_HANDLED` when the word is outside the verified scope
|
|
206
|
-
# @raise [ArgumentError] if the word is table-executed and the positional argument count
|
|
207
|
-
# does not match what its row admits
|
|
208
|
-
# @raise [Bluebook::DSL::Malformed] if a single-fill row names a `blank_message:` and the
|
|
209
|
-
# value is blank, or the `calls:` target itself refuses the declaration
|
|
210
|
-
# @raise [Runtime::WiringError] if `shape_for` names a kind this method has no arm for
|
|
32
|
+
# Executes a table-admitted word via the shape `shape_for` found for it, or returns
|
|
33
|
+
# NOT_HANDLED so the caller can fall back to its own "not yet implemented" refusal.
|
|
211
34
|
def try(builder, context, word, args, kwargs, block, rows)
|
|
212
35
|
shape = shape_for(context, word, rows)
|
|
213
36
|
return NOT_HANDLED unless shape
|
|
@@ -218,40 +41,18 @@ module Hecks
|
|
|
218
41
|
when :zero_arg then try_zero_arg(builder, shape[:keyword], args)
|
|
219
42
|
when :single_fill then try_single_fill(builder, shape[:fills], shape[:argument], args, kwargs)
|
|
220
43
|
else
|
|
221
|
-
# `shape_for` names exactly four kinds
|
|
222
|
-
#
|
|
223
|
-
# added there without a matching arm here. Falling through
|
|
224
|
-
# silently would return bare `nil` from what the caller
|
|
225
|
-
# (`WordGate#method_missing`) reads as "handled" (anything
|
|
226
|
-
# other than NOT_HANDLED counts), so a self-hosted DSL word
|
|
227
|
-
# would silently execute as a no-op instead of raising the
|
|
228
|
-
# same "not yet implemented" refusal a genuinely unmigrated
|
|
229
|
-
# word already gets.
|
|
44
|
+
# Backstop: `shape_for` names exactly four kinds; falling through would return nil,
|
|
45
|
+
# which the caller reads as "handled", silently turning the word into a no-op.
|
|
230
46
|
raise Runtime::WiringError,
|
|
231
47
|
"no dispatcher handles shape #{shape[:kind].inspect} — add one before shape_for can produce it"
|
|
232
48
|
end
|
|
233
49
|
end
|
|
234
50
|
|
|
235
|
-
# Classifies a (context, word) pair into the table-executable
|
|
236
|
-
#
|
|
237
|
-
# The one place row shape is judged — returns a small Hash naming
|
|
238
|
-
# which of the four safe shapes (context, word) is, or `nil` if
|
|
239
|
-
# it falls outside this slice's own verified scope. No argument
|
|
240
|
-
# values are read here; this only ever looks at the table.
|
|
51
|
+
# Classifies a (context, word) pair into one of the four table-executable shapes, or
|
|
52
|
+
# nil when it falls outside this module's verified scope.
|
|
241
53
|
#
|
|
242
|
-
#
|
|
243
|
-
#
|
|
244
|
-
# checks before it. Splitting per shape would mean re-deriving or
|
|
245
|
-
# threading those locals across method boundaries for a
|
|
246
|
-
# classification that is only ever read top-to-bottom once, here.
|
|
247
|
-
#
|
|
248
|
-
# @param context [String] the grammar context to look the word up under
|
|
249
|
-
# @param word [String] the DSL word; retired rows never match
|
|
250
|
-
# @param rows [Hash{Symbol => Array<Hash{Symbol => String}>}] the grammar table, with
|
|
251
|
-
# `:keywords` and `:arguments` row lists
|
|
252
|
-
# @return [Hash{Symbol => Object}, nil] `:kind` is `:calls_through` (with `:calls`, the
|
|
253
|
-
# target method name), `:opens_block` or `:zero_arg` (with `:keyword`, the row), or
|
|
254
|
-
# `:single_fill` (with `:fills` and `:argument`); nil when the word is out of scope
|
|
54
|
+
# Early-return chain: each check depends on locals from the ones before it, read once
|
|
55
|
+
# top-to-bottom; splitting per shape would just re-thread the same locals across methods.
|
|
255
56
|
# rubocop:disable-next Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
256
57
|
def shape_for(context, word, rows)
|
|
257
58
|
keyword = rows[:keywords].find { |k| k[:context] == context && k[:word] == word && k[:status] != "retired" }
|
|
@@ -277,44 +78,14 @@ module Hecks
|
|
|
277
78
|
{ kind: :single_fill, fills: fills, argument: arg }
|
|
278
79
|
end
|
|
279
80
|
|
|
280
|
-
# Forwards a word's whole call to the builder method its row's `calls:`
|
|
281
|
-
#
|
|
282
|
-
# `keyword[:calls]` names a real Ruby method whose whole call —
|
|
283
|
-
# every positional, every kwarg, the block, all of it — forwards
|
|
284
|
-
# here unchanged. No argument-shape interpretation at all,
|
|
285
|
-
# deliberately: the target method (`AttributeCollector#
|
|
286
|
-
# attribute_impl`, etc.) already does its own, real, hand-
|
|
287
|
-
# written argument handling; this is a pure, transparent `send`,
|
|
288
|
-
# the lowest-risk possible shape for a word whose own logic is
|
|
289
|
-
# too complex to re-derive from the table (type-quoting refusal,
|
|
290
|
-
# closed-set synthesis, pattern validation, ...).
|
|
291
|
-
#
|
|
292
|
-
# @param builder [Bluebook::DSL::WordGate] the builder instance to send the call to
|
|
293
|
-
# @param calls [String, Symbol] the target method's name, such as `"attribute_impl"`
|
|
294
|
-
# @param args [Array<Object>] positional arguments, forwarded unchanged
|
|
295
|
-
# @param kwargs [Hash{Symbol => Object}] keyword arguments, forwarded unchanged
|
|
296
|
-
# @param block [Proc, nil] the block, forwarded unchanged
|
|
297
|
-
# @return [Object] whatever the target method returns
|
|
298
|
-
# @raise [Bluebook::DSL::Malformed] if the target method refuses the declaration
|
|
81
|
+
# Forwards a word's whole call, unchanged, to the builder method its row's `calls:`
|
|
82
|
+
# names — no argument-shape interpretation; the target method already does its own.
|
|
299
83
|
def try_calls_through(builder, calls, args, kwargs, block)
|
|
300
84
|
builder.send(calls, *args, **kwargs, &block)
|
|
301
85
|
end
|
|
302
86
|
|
|
303
|
-
# Builds a child construct from a block-opening word and appends it to the builder's
|
|
304
|
-
#
|
|
305
|
-
# @param builder [Bluebook::DSL::WordGate] the builder whose list receives the child
|
|
306
|
-
# @param keyword [Hash{Symbol => String}] the word's Keyword row; `:opens` names the
|
|
307
|
-
# child builder class without its `Builder` suffix, and the pair of `:context` and
|
|
308
|
-
# `:word` must be a `SAFE_OPENS_BLOCK` key
|
|
309
|
-
# @param args [Array<Object>] the call's positional arguments; exactly one, the child's
|
|
310
|
-
# name
|
|
311
|
-
# @param kwargs [Hash{Symbol => Object}] the call's keyword arguments
|
|
312
|
-
# @param block [Proc, nil] the child's body, evaluated against the child builder
|
|
313
|
-
# @return [Array<Object>, Object] the builder's list with the built child appended, or
|
|
314
|
-
# `NOT_HANDLED` when any keyword argument was given
|
|
315
|
-
# @raise [ArgumentError] if the call does not carry exactly one positional argument
|
|
316
|
-
# @raise [KeyError] if the row's context and word are not in `SAFE_OPENS_BLOCK`
|
|
317
|
-
# @raise [Bluebook::DSL::Malformed] if the child builder refuses its own body
|
|
87
|
+
# Builds a child construct from a block-opening word and appends it to the builder's
|
|
88
|
+
# list named by its row in `SAFE_OPENS_BLOCK`.
|
|
318
89
|
def try_opens_block(builder, keyword, args, kwargs, block)
|
|
319
90
|
return NOT_HANDLED unless kwargs.empty?
|
|
320
91
|
|
|
@@ -331,14 +102,6 @@ module Hecks
|
|
|
331
102
|
end
|
|
332
103
|
|
|
333
104
|
# Stores a zero-argument word's value into the instance variable its row's `fills:` names.
|
|
334
|
-
#
|
|
335
|
-
# @param builder [Bluebook::DSL::WordGate] the builder whose instance variable is set
|
|
336
|
-
# @param keyword [Hash{Symbol => String}] the word's Keyword row, read for `:context`,
|
|
337
|
-
# `:fills` and `:word`
|
|
338
|
-
# @param args [Array<Object>] the call's positional arguments, which must be empty
|
|
339
|
-
# @return [Symbol, true] the stored value: the word itself as a Symbol when sibling words
|
|
340
|
-
# share the same `fills:` target (`core`/`generic`/`supporting`), otherwise `true`
|
|
341
|
-
# @raise [ArgumentError] if any positional argument was given
|
|
342
105
|
def try_zero_arg(builder, keyword, args)
|
|
343
106
|
raise ArgumentError, "wrong number of arguments (given #{args.size}, expected 0)" unless args.empty?
|
|
344
107
|
|
|
@@ -352,19 +115,7 @@ module Hecks
|
|
|
352
115
|
end
|
|
353
116
|
|
|
354
117
|
# Coerces a word's one positional argument and stores it, appending when the target
|
|
355
|
-
#
|
|
356
|
-
#
|
|
357
|
-
# @param builder [Bluebook::DSL::WordGate] the builder whose instance variable is filled
|
|
358
|
-
# @param fills [String] the instance variable's name, without the `@`
|
|
359
|
-
# @param arg [Hash{Symbol => String}] the word's single Argument row, read for `:kind`,
|
|
360
|
-
# `:coerce` and `:blank_message`
|
|
361
|
-
# @param args [Array<Object>] the call's positional arguments; exactly one
|
|
362
|
-
# @param kwargs [Hash{Symbol => Object}] the call's keyword arguments
|
|
363
|
-
# @return [Object] the stored value, or the Array it was appended to, or `NOT_HANDLED`
|
|
364
|
-
# when any keyword argument was given
|
|
365
|
-
# @raise [ArgumentError] if the call does not carry exactly one positional argument
|
|
366
|
-
# @raise [Bluebook::DSL::Malformed] if the row names a `blank_message:` and the coerced
|
|
367
|
-
# value is blank
|
|
118
|
+
# ivar already holds an Array and assigning otherwise.
|
|
368
119
|
def try_single_fill(builder, fills, arg, args, kwargs)
|
|
369
120
|
return NOT_HANDLED unless kwargs.empty?
|
|
370
121
|
|
|
@@ -2,13 +2,8 @@ require_relative "word_gate"
|
|
|
2
2
|
module Hecks
|
|
3
3
|
module Bluebook
|
|
4
4
|
module DSL
|
|
5
|
-
# Parses a `.hecksagon` file's
|
|
6
|
-
#
|
|
7
|
-
# (`persisted_by`, `projected_by`, ...), which framework/vendored
|
|
8
|
-
# bluebooks it attaches, which external events it subscribes to, and
|
|
9
|
-
# its bare chapter-root port. Kept separate from the bluebook itself
|
|
10
|
-
# (the domain's own declared model) because wiring is an operational
|
|
11
|
-
# decision, not a fact the domain states about itself.
|
|
5
|
+
# Parses a `.hecksagon` file's DSL block into a Hecksagon: a domain's adapter bindings,
|
|
6
|
+
# framework/vendored attachments and subscriptions — wiring, not part of the bluebook.
|
|
12
7
|
class HecksagonBuilder
|
|
13
8
|
GRAMMAR_CONTEXT = "Hecksagon".freeze
|
|
14
9
|
|
|
@@ -20,7 +15,6 @@ module Hecks
|
|
|
20
15
|
|
|
21
16
|
attr_reader :binds, :subscriptions, :framework_members, :vendored_bluebooks
|
|
22
17
|
|
|
23
|
-
# @param domain [String] name of the domain whose wiring this hecksagon declares
|
|
24
18
|
def initialize(domain)
|
|
25
19
|
@domain = domain
|
|
26
20
|
@binds = []
|
|
@@ -31,168 +25,59 @@ module Hecks
|
|
|
31
25
|
@translates = []
|
|
32
26
|
end
|
|
33
27
|
|
|
34
|
-
# Marks
|
|
35
|
-
#
|
|
36
|
-
# Framework and vendored packages get the mark automatically from
|
|
37
|
-
# those words; they never write `bounded` in their own bluebooks.
|
|
38
|
-
# A bounded chapter wraps in its own module (no Object shortcut)
|
|
39
|
-
# and must declare at least one `translates` ACL or boot refuses.
|
|
40
|
-
#
|
|
41
|
-
# @return [Boolean] true
|
|
28
|
+
# Marks this chapter as a bounded context; framework/vendored attachments set it too.
|
|
29
|
+
# Must declare at least one `translates` ACL or boot refuses.
|
|
42
30
|
def bounded
|
|
43
31
|
@bounded = true
|
|
44
32
|
end
|
|
45
33
|
|
|
46
|
-
# Subscribes
|
|
47
|
-
#
|
|
48
|
-
# @param event [String, Symbol] the external event's name
|
|
49
|
-
# @return [Array<String>] every subscription declared so far, this one last
|
|
34
|
+
# Subscribes to an event from outside this domain's own bluebook.
|
|
50
35
|
def subscribe(event) = @subscriptions << event.to_s
|
|
51
36
|
|
|
52
|
-
# Attaches a framework member
|
|
53
|
-
#
|
|
54
|
-
# A framework/ member this domain wants attached —
|
|
55
|
-
# Governance, Identity, whatever else lands beside them.
|
|
56
|
-
# Attaching one is a wiring decision, the same kind `persisted_by`/
|
|
57
|
-
# `projected_by` already are, so it lives here rather than as a
|
|
58
|
-
# fact stated in the domain's own bluebook. Recorded onto this
|
|
59
|
-
# hecksagon, the same way `subscribe` records onto its own
|
|
60
|
-
# `subscriptions` — and loads the member's bluebook then its own
|
|
61
|
-
# hecksagon into whatever registry this one is loading into, see
|
|
62
|
-
# `Framework.load!`.
|
|
63
|
-
#
|
|
64
|
-
# @param name [String, Symbol] the member's name, such as `"Governance"`
|
|
65
|
-
# @return [Boolean, nil] true when this call loaded the member's bluebook, nil when the
|
|
66
|
-
# current registry already held it
|
|
67
|
-
# @raise [Runtime::WiringError] if no framework member has that name
|
|
37
|
+
# Attaches a framework member (e.g. Governance) and loads it into the current registry.
|
|
68
38
|
def uses_framework(name)
|
|
69
39
|
@framework_members << name.to_s
|
|
70
40
|
Hecks::Framework.load!(name)
|
|
71
|
-
#
|
|
72
|
-
#
|
|
73
|
-
# the anti-corruption layer. Not written in the framework
|
|
74
|
-
# bluebook itself.
|
|
41
|
+
# Marks the framework member as bounded; the consumer's own hecksagon is the
|
|
42
|
+
# anti-corruption layer.
|
|
75
43
|
Hecks.current_registry&.mark_bounded(name.to_s)
|
|
76
44
|
end
|
|
77
45
|
|
|
78
46
|
# Attaches a vendored embryonaut bluebook to this domain and loads its files into the
|
|
79
|
-
#
|
|
80
|
-
#
|
|
81
|
-
# A vendored, external bluebook this domain wants attached — same
|
|
82
|
-
# wiring-decision shape `uses_framework` already is, one level
|
|
83
|
-
# further out: not a member shipped inside hecks's own lib/,
|
|
84
|
-
# but a separate package (embryonaut_bluebooks) vendored into this
|
|
85
|
-
# project's own checkout. See EmbryonautBluebook's own header for
|
|
86
|
-
# the full reasoning on why its root can't be a fixed constant the
|
|
87
|
-
# way Framework::ROOT is, and for the recovery provenance.
|
|
88
|
-
#
|
|
89
|
-
# Recorded onto @vendored_bluebooks, same shape `uses_framework`
|
|
90
|
-
# already gives @framework_members — a separate list on purpose:
|
|
91
|
-
# `framework_members` is load-bearing for `refuse_ungoverned_roles!`
|
|
92
|
-
# (`Registry::Verification`) and for Governance's own attachment
|
|
93
|
-
# check; conflating the two would make a vendored bluebook attachment
|
|
94
|
-
# satisfy a Governance check it has nothing to do with.
|
|
95
|
-
#
|
|
96
|
-
# @param name [String, Symbol] the vendored package's directory name under
|
|
97
|
-
# `vendor/embryonaut_bluebooks/`
|
|
98
|
-
# @return [Array<String>, nil] paths of the `.bluebook` files this call loaded, or nil
|
|
99
|
-
# when the current registry already held the bluebook
|
|
100
|
-
# @raise [Runtime::WiringError] if the current registry has no root to vendor from, or
|
|
101
|
-
# no vendored bluebook of that name exists under it
|
|
47
|
+
# registry. Recorded separately from @framework_members, which is load-bearing for
|
|
48
|
+
# governance checks.
|
|
102
49
|
def uses_embryonaut_bluebook(name)
|
|
103
50
|
@vendored_bluebooks << name.to_s
|
|
104
51
|
Hecks::EmbryonautBluebook.load!(name)
|
|
105
|
-
#
|
|
106
|
-
#
|
|
107
|
-
# (`"membership"` → `Membership`).
|
|
52
|
+
# Marks the chapter bounded, same as `uses_framework`; the directory name Pascal-cases
|
|
53
|
+
# to the chapter name (`"membership"` → `Membership`).
|
|
108
54
|
Hecks.current_registry&.mark_bounded(Hecks::Naming.pascal(name.to_s))
|
|
109
55
|
end
|
|
110
56
|
|
|
111
|
-
# Declares a port at the hecksagon's root
|
|
112
|
-
#
|
|
113
|
-
# The primary port, bare at the root — belongs to the chapter as a
|
|
114
|
-
# whole, not one aggregate. `BindingProxy#port` is the aggregate-
|
|
115
|
-
# scoped sibling (`Payments::Payment.port("Gateway") do ... end`);
|
|
116
|
-
# this is what's left when a port isn't about any one record. The
|
|
117
|
-
# bluebook must already be built and registered, since a hecksagon
|
|
118
|
-
# loads after its bluebook, and this attaches to that real, final
|
|
119
|
-
# object directly rather than building a second copy MetaValidator
|
|
120
|
-
# would have to know how to reconstruct.
|
|
121
|
-
#
|
|
122
|
-
# Answers the `port` word through the table's `calls:` column —
|
|
123
|
-
# item #13's full metaprogrammed dispatch (slice 5). Not
|
|
124
|
-
# bootstrap-reachable (checked directly — no core/attached chapter
|
|
125
|
-
# declares a Hecksagon of its own). Reached through `WordGate`'s
|
|
126
|
-
# `word_gate_dispatch`, called explicitly below since
|
|
127
|
-
# `HecksagonBuilder`'s own class-level `method_missing` (the
|
|
128
|
-
# open-verb catch-all beneath this) always wins over the module's —
|
|
129
|
-
# see `word_gate.rb`'s own header for the full mechanism.
|
|
130
|
-
#
|
|
131
|
-
# @param name [String] the port's name
|
|
132
|
-
# @yield the port body, evaluated against a `DomainPortBuilder`: either `verb`/`signal`
|
|
133
|
-
# or `operation`/`tells`/`asks` blocks
|
|
134
|
-
# @return [Bluebook::Port, Bluebook::DomainPort] the built port: a verb-shaped `Port`
|
|
135
|
-
# registered on the current registry, or a `DomainPort` attached to the bluebook
|
|
136
|
-
# @raise [Bluebook::DSL::Malformed] if the current registry holds no bluebook for this
|
|
137
|
-
# domain, or the body declares both a verb and operations, neither, or an operation
|
|
138
|
-
# the port grammar refuses
|
|
57
|
+
# Declares a port at the hecksagon's root — the chapter as a whole, not one aggregate.
|
|
139
58
|
def port_impl(name, &block)
|
|
140
59
|
bluebook_ir = Hecks.current_registry.bluebook(@domain) or
|
|
141
60
|
raise Malformed, "#{@domain} declares no such bluebook — a port needs one to belong to"
|
|
142
61
|
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
# dynamic extent, currently this file's own BindingProxy-minting
|
|
146
|
-
# one, which would turn a bare constant inside an operation's
|
|
147
|
-
# `reference_to`/`attribute` into another BindingProxy instead of
|
|
148
|
-
# a name.
|
|
62
|
+
# Swaps the active ConstShim resolver to plain passthrough — without it a bare constant
|
|
63
|
+
# inside `reference_to`/`attribute` would resolve to a BindingProxy instead of a name.
|
|
149
64
|
built = ConstShim.with(->(const) { const }) { DomainPortBuilder.build(name, &block) }
|
|
150
65
|
|
|
151
|
-
#
|
|
152
|
-
#
|
|
153
|
-
# way `Hecks.port`'s top-level method already does, not attached
|
|
154
|
-
# to this bluebook's own IR the way an operations-shaped
|
|
155
|
-
# `DomainPort` is.
|
|
66
|
+
# A verb-shaped port is a plain `Port`, registered like `Hecks.port`'s top-level method,
|
|
67
|
+
# not attached to this bluebook's IR the way an operations-shaped `DomainPort` is.
|
|
156
68
|
return Hecks.current_registry.add_port(built) if built.is_a?(Port)
|
|
157
69
|
|
|
158
70
|
bluebook_ir.add_port(built)
|
|
159
71
|
end
|
|
160
72
|
|
|
161
|
-
# A
|
|
162
|
-
#
|
|
163
|
-
# builds the EXACT SAME `Policy` a `policy` block inside this
|
|
164
|
-
# domain's own `.bluebook` would (same `on_impl`/`trigger_impl`,
|
|
165
|
-
# same `PolicyInterpreter` runtime — reusing `PolicyBuilder`
|
|
166
|
-
# directly, zero new runtime semantics). What's new is only WHERE
|
|
167
|
-
# it can be written: a cross-domain reaction is a wiring/context-
|
|
168
|
-
# mapping decision (this chapter conforming to a foreign chapter's
|
|
169
|
-
# published event), the same kind of decision `port`/
|
|
170
|
-
# `uses_framework` already are — not a fact this domain's own
|
|
171
|
-
# model states about itself, which `policy` (inside the bluebook)
|
|
172
|
-
# remains the right word for.
|
|
173
|
-
#
|
|
174
|
-
# MUST BE A BLOCK, not `translates Event, into: Command` — a flat
|
|
175
|
-
# call's arguments are evaluated eagerly, under THIS builder's own
|
|
176
|
-
# `ConstShim` resolver (`BindingProxy.namespace`, set up by
|
|
177
|
-
# `self.build` below), which mints a `BindingProxy` INSTANCE per
|
|
178
|
-
# segment and cannot answer a further `::` (it is not a Module) —
|
|
179
|
-
# a multi-segment reference like `Deploy::Tenant::TenantProvisioned`
|
|
180
|
-
# would raise before this method ever ran. `port_impl`'s own
|
|
181
|
-
# `ConstShim.with(->(const) { const })` swap only works because
|
|
182
|
-
# its own callers never pass a multi-segment bare constant as an
|
|
183
|
-
# eagerly-evaluated argument — everything of that shape lives
|
|
184
|
-
# inside ITS block, evaluated later, under the swapped resolver.
|
|
185
|
-
# A block defers evaluation the same way; a flat call cannot.
|
|
73
|
+
# A cross-domain reaction, built as the same `Policy` an in-bluebook `policy` block would.
|
|
74
|
+
# Must be a block — the eager const resolver here can't handle multi-segment references.
|
|
186
75
|
def translates(name, &block)
|
|
187
76
|
bluebook_ir = Hecks.current_registry.bluebook(@domain) or
|
|
188
77
|
raise Malformed, "#{@domain} declares no such bluebook — translates needs one to attach its reaction to"
|
|
189
78
|
|
|
190
|
-
#
|
|
191
|
-
#
|
|
192
|
-
# `ScopedConstant`, not the bare passthrough `port_impl` swaps
|
|
193
|
-
# to, because `on`/`trigger` here take genuinely multi-segment
|
|
194
|
-
# references (`Deploy::Tenant::TenantProvisioned`), not a
|
|
195
|
-
# single-segment type name.
|
|
79
|
+
# Same resolver `policy` blocks use for `on`/`trigger` — a ScopedConstant, not the bare
|
|
80
|
+
# passthrough `port_impl` swaps to, since these take multi-segment references.
|
|
196
81
|
resolver = ->(const) { ConstShim::ScopedConstant.for(const) }
|
|
197
82
|
built = ConstShim.with(resolver) { PolicyBuilder.build(name, &block) }
|
|
198
83
|
|
|
@@ -201,58 +86,18 @@ module Hecks
|
|
|
201
86
|
end
|
|
202
87
|
|
|
203
88
|
# Assembles the collected binds, subscriptions and attachments into a `Hecksagon`.
|
|
204
|
-
#
|
|
205
|
-
# No ungoverned-role check here — see
|
|
206
|
-
# Registry::Verification#refuse_ungoverned_roles!. It lives outside
|
|
207
|
-
# per-block `build`, alongside `environment:`
|
|
208
|
-
# (Runtime::Loader.boot's comment has the provenance): a domain
|
|
209
|
-
# split across multiple hecksagon blocks (base + an
|
|
210
|
-
# `environments/<name>.hecksagon` overlay) would have every
|
|
211
|
-
# block but the one declaring `uses_framework "Governance"`
|
|
212
|
-
# refused here, even though `Registry#add_hecksagon` merges them
|
|
213
|
-
# into one Hecksagon before anything ever dispatches against it.
|
|
214
|
-
# Checking the merged result once, at verify! time — after every
|
|
215
|
-
# file for this domain has loaded — is both more permissive (no
|
|
216
|
-
# need to repeat `uses_framework` in every file) and strictly
|
|
217
|
-
# more correct (a check against an incomplete, not-yet-merged
|
|
218
|
-
# hecksagon can never see the real final shape).
|
|
219
|
-
#
|
|
220
|
-
# @return [Bluebook::Hecksagon] this block's wiring, which `Registry#add_hecksagon` merges
|
|
221
|
-
# with any other block declared for the same domain
|
|
89
|
+
# No ungoverned-role check here — it runs once on the merged result at verify! time.
|
|
222
90
|
def build
|
|
223
91
|
Hecksagon.new(domain: @domain, binds: @binds, subscriptions: @subscriptions,
|
|
224
92
|
framework_members: @framework_members, vendored_bluebooks: @vendored_bluebooks,
|
|
225
93
|
bounded: @bounded, translates: @translates)
|
|
226
94
|
end
|
|
227
95
|
|
|
228
|
-
# Records any verb the grammar
|
|
229
|
-
#
|
|
230
|
-
# **Domain-level default binds** — `persisted_by "Heki"` bare, at the top
|
|
231
|
-
# of a hecksagon block, applies to every aggregate in this domain
|
|
232
|
-
# that doesn't declare its own override. Mirrors `BindingProxy`'s own
|
|
233
|
-
# `method_missing` one level down (`aggregate:` filled in there,
|
|
234
|
-
# `nil` here) — generic over verb name, not hardcoded to
|
|
235
|
-
# `persisted_by`/`projected_by` specifically, so any future verb
|
|
236
|
-
# gets a domain-level default for free too. See `Hecksagon#bind_for`
|
|
237
|
-
# for the fallback lookup this feeds.
|
|
238
|
-
#
|
|
239
|
-
# @param verb [Symbol] the word called, such as `:persisted_by`
|
|
240
|
-
# @param args [Array<Object>] positional arguments; the first names the adapter
|
|
241
|
-
# @param kwargs [Hash{Symbol => Object}] keyword arguments; `:role` is kept on the bind
|
|
242
|
-
# @yield an optional block, called once after the bind is recorded
|
|
243
|
-
# @return [Object] this builder after recording a bind, or the grammar word's own result
|
|
244
|
-
# when `verb` is one the `Hecksagon` grammar admits
|
|
245
|
-
# @raise [NoMethodError] if `verb` is no grammar word and names no adapter
|
|
246
|
-
# @raise [Bluebook::DSL::Malformed] if the grammar admits `verb` only in another context,
|
|
247
|
-
# or admits it here and its implementation refuses the declaration
|
|
96
|
+
# Records any verb the grammar doesn't own as a domain-wide default bind, e.g. bare
|
|
97
|
+
# `persisted_by "Heki"` at the top of a block, applied unless an aggregate overrides it.
|
|
248
98
|
def method_missing(verb, *args, **kwargs, &block)
|
|
249
|
-
#
|
|
250
|
-
#
|
|
251
|
-
# `WordGate#word_gate_dispatch`'s own header for why this class
|
|
252
|
-
# needs to call it explicitly rather than including it the
|
|
253
|
-
# ordinary way. Only once that says "not admitted" does the
|
|
254
|
-
# genuinely open-ended `persisted_by "Heki"`-style bind
|
|
255
|
-
# vocabulary below get a turn.
|
|
99
|
+
# Grammar words (like `port`) get first refusal via explicit dispatch; only when that's
|
|
100
|
+
# not admitted does the open-ended `persisted_by`-style bind vocabulary below apply.
|
|
256
101
|
result = word_gate_dispatch(verb, args, kwargs, block)
|
|
257
102
|
return result unless result.equal?(WordGate::NOT_ADMITTED)
|
|
258
103
|
|
|
@@ -267,14 +112,6 @@ module Hecks
|
|
|
267
112
|
|
|
268
113
|
# Evaluates a `Hecks.hecksagon` block with bare `Domain::Aggregate` constants resolving to
|
|
269
114
|
# bind-collecting proxies, and returns the wiring it declared.
|
|
270
|
-
#
|
|
271
|
-
# @param domain [String] name of the domain being wired
|
|
272
|
-
# @yield the hecksagon body, evaluated with the builder as `self`; may be omitted
|
|
273
|
-
# @return [Bluebook::Hecksagon] the declared wiring
|
|
274
|
-
# @raise [Bluebook::DSL::Malformed] if a `port` names no registered bluebook or aggregate,
|
|
275
|
-
# or declares a shape the port grammar refuses
|
|
276
|
-
# @raise [Runtime::WiringError] if `uses_framework` or `uses_embryonaut_bluebook` names
|
|
277
|
-
# something that cannot be found
|
|
278
115
|
def self.build(domain, &block)
|
|
279
116
|
builder = new(domain)
|
|
280
117
|
resolver = ->(name) { BindingProxy.namespace(name, builder.binds) }
|