hecks 2.8.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +4 -6
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +17 -98
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +5 -48
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +31 -141
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +14 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +25 -31
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +16 -69
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -194
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +19 -111
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +53 -267
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +43 -305
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +6 -21
- data/lib/hecks/bluebook/model_check.rb +100 -597
- data/lib/hecks/bluebook/pattern_subset.rb +11 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +4 -23
- data/lib/hecks/cli/document.rb +3 -21
- data/lib/hecks/cli/ir.rb +3 -5
- data/lib/hecks/cli/mcp.rb +2 -3
- data/lib/hecks/cli/mcp_door.rb +19 -114
- data/lib/hecks/cli/model_check.rb +18 -85
- data/lib/hecks/cli/project_cli.rb +7 -40
- data/lib/hecks/cli/project_diagrams.rb +0 -7
- data/lib/hecks/cli/run.rb +12 -58
- data/lib/hecks/cli/smoke_test.rb +2 -16
- data/lib/hecks/cli/stores.rb +1 -2
- data/lib/hecks/cli.rb +18 -24
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +30 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +12 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +82 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_door_scope.rb +9 -90
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +61 -64
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +6 -25
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +18 -124
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +23 -103
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projections/bootstrap_table.rb +11 -43
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +150 -678
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +20 -582
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +2 -15
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +42 -134
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +3 -6
- data/lib/hecks/release/runner/commands.rb +2 -4
- data/lib/hecks/release/runner/gem_publisher.rb +2 -3
- data/lib/hecks/release/runner/npm_publisher.rb +6 -20
- data/lib/hecks/release/runner/preflight.rb +4 -19
- data/lib/hecks/release/runner/tagger.rb +2 -9
- data/lib/hecks/release/runner.rb +3 -32
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +124 -306
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +64 -219
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +117 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +99 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +141 -568
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks.rb +26 -81
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- metadata +3 -2
|
@@ -3,32 +3,12 @@ require_relative "expression/ast_json"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Bluebook
|
|
6
|
-
# A field
|
|
7
|
-
#
|
|
8
|
-
# :customer_status, from: :"customer.status"` declares that this
|
|
9
|
-
# aggregate's own `:customer_status` is a copy of the target's own
|
|
10
|
-
# `:status`, kept fresh by a rebuild sweep rather than read live at
|
|
11
|
-
# rule-evaluation time. `reference` names the local reference
|
|
12
|
-
# attribute to walk through (`:customer`, minted by this
|
|
13
|
-
# aggregate's own `reference_to Customer`); `remote_field` names
|
|
14
|
-
# the scalar on the target aggregate to copy.
|
|
6
|
+
# A field copied from a `reference_to` target, kept fresh by a rebuild sweep (S12, ADR 0025).
|
|
7
|
+
# `reference` is the local reference attribute to walk; `remote_field` the target's scalar.
|
|
15
8
|
ProjectedField = Struct.new(:name, :reference, :remote_field, keyword_init: true)
|
|
16
9
|
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
# everything declared on it. The chain is model objects end to end —
|
|
20
|
-
# reference resolution and hecks_fqn both walk it.
|
|
21
|
-
#
|
|
22
|
-
# The holding half, and nothing else. Every line below restates what
|
|
23
|
-
# `language/bluebook/aggregate.bluebook` already declares — the field
|
|
24
|
-
# list, said again as readers, again as constructor keywords, and
|
|
25
|
-
# again as an emission. That triplication is what a generator removes;
|
|
26
|
-
# `Behaviour::Aggregate` carries everything that is not derivable from
|
|
27
|
-
# the declaration, so regenerating this file can never be lossy.
|
|
28
|
-
#
|
|
29
|
-
# Prototype: hand-written in the shape a generator would emit, to
|
|
30
|
-
# prove the seam before the generator exists. `bin/project_model`
|
|
31
|
-
# would own this file; behaviour/aggregate.rb stays hand-written.
|
|
10
|
+
# An aggregate: carries its own identity and sits in the owner chain below its chapter.
|
|
11
|
+
# The holding half only; `Behaviour::Aggregate` carries what the declaration cannot derive.
|
|
32
12
|
class Aggregate
|
|
33
13
|
include Construct
|
|
34
14
|
include Hecks::IR
|
|
@@ -42,20 +22,10 @@ module Hecks
|
|
|
42
22
|
value_objects: many(:value_objects),
|
|
43
23
|
commands: many(:commands),
|
|
44
24
|
invariants: -> { invariants.map { |rule| Expression::AstJson.rule_row(rule) } },
|
|
45
|
-
#
|
|
46
|
-
# 0025) — the aggregate's own named `given`s, the declaration a
|
|
47
|
-
# referencing command's own (already-resolved) `givens` entry
|
|
48
|
-
# came from. Both sides of "declared once, referenced many"
|
|
49
|
-
# are real IR, the same shape a value object's type and an
|
|
50
|
-
# attribute's own reference to it both are.
|
|
25
|
+
# The named `given`s a referencing command's resolved `givens` entry came from.
|
|
51
26
|
preconditions: -> { preconditions.map { |rule| Expression::AstJson.rule_row(rule) } },
|
|
52
|
-
#
|
|
53
|
-
# `
|
|
54
|
-
# whether a new field leaves an existing record with something
|
|
55
|
-
# genuinely absent, and a projected field's own absence story
|
|
56
|
-
# is different — a record predating the `projects` declaration
|
|
57
|
-
# is expected to be missing it until the rebuild sweep runs,
|
|
58
|
-
# not a shape drift a translation needs to explain.
|
|
27
|
+
# Not folded into `attributes`: EraGuard::ShapeDiff walks those, and a record predating
|
|
28
|
+
# `projects` is expected to lack this field until the rebuild sweep runs.
|
|
59
29
|
projected_fields: lambda {
|
|
60
30
|
projected_fields.map do |field|
|
|
61
31
|
{ name: field.name.to_s, reference: field.reference.to_s, remote_field: field.remote_field.to_s }
|
|
@@ -64,11 +34,7 @@ module Hecks
|
|
|
64
34
|
lifecycle: one(:lifecycle),
|
|
65
35
|
entities: many(:entities),
|
|
66
36
|
queries: many(:queries),
|
|
67
|
-
# Additive
|
|
68
|
-
# the same "regenerate deliberately" wire-format change
|
|
69
|
-
# ir_golden_spec.rb's own header describes; no existing key
|
|
70
|
-
# moves. See docs/decisions (rust/project/ports.rb) for the
|
|
71
|
-
# first reader of this.
|
|
37
|
+
# Additive: domains that declare no port emit `ports: []`; no existing key moves.
|
|
72
38
|
ports: many(:ports),
|
|
73
39
|
provenance: :provenance
|
|
74
40
|
)
|
|
@@ -77,39 +43,7 @@ module Hecks
|
|
|
77
43
|
:projected_fields, :identified_by, :identity_paths, :identity_heads, :lifecycle,
|
|
78
44
|
:entities, :queries, :policies, :ports, :reference_targets, :provenance
|
|
79
45
|
|
|
80
|
-
# Assigns
|
|
81
|
-
# behaviour's own `settle` — derived identity, name indexes and
|
|
82
|
-
# owner stamping, none of which the declaration states.
|
|
83
|
-
#
|
|
84
|
-
# @param name [String, Symbol] the aggregate's declared name
|
|
85
|
-
# @param description [String, nil] the aggregate's declared prose description
|
|
86
|
-
# @param attributes [Array<Bluebook::Attribute>] the aggregate's declared fields
|
|
87
|
-
# @param value_objects [Array<Class>] the value object classes (`Bluebook::ValueObject`
|
|
88
|
-
# subclasses) declared on this aggregate
|
|
89
|
-
# @param commands [Array<Class>] the command classes (`Bluebook::Command` subclasses)
|
|
90
|
-
# declared on this aggregate
|
|
91
|
-
# @param invariants [Array<Bluebook::Invariant>] the aggregate-level rules that must
|
|
92
|
-
# always hold
|
|
93
|
-
# @param preconditions [Array<Bluebook::Given>] the aggregate's own named `given`s, a
|
|
94
|
-
# referencing command's own resolved `givens` entry can point back at
|
|
95
|
-
# @param projected_fields [Array<Bluebook::ProjectedField>] the declared `projects`
|
|
96
|
-
# fields, copied from another aggregate's own state by the rebuild sweep
|
|
97
|
-
# @param identified_by [String, Symbol, Array<String, Symbol>] the identity path(s)
|
|
98
|
-
# this aggregate is addressed by
|
|
99
|
-
# @param lifecycle [Bluebook::Lifecycle, nil] the aggregate's declared state machine,
|
|
100
|
-
# or `nil` if it declares none
|
|
101
|
-
# @param entities [Array<Class>] the entity classes (`Bluebook::Entity` subclasses)
|
|
102
|
-
# nested directly under this aggregate
|
|
103
|
-
# @param queries [Array<Bluebook::Query>] the queries declared directly on this
|
|
104
|
-
# aggregate
|
|
105
|
-
# @param policies [Array<Bluebook::Policy>] the reactions hoisted onto this aggregate
|
|
106
|
-
# from the chapter that assembled it
|
|
107
|
-
# @param ports [Array<Bluebook::DomainPort>] the aggregate-scoped ports attached after
|
|
108
|
-
# this aggregate was built
|
|
109
|
-
# @param reference_targets [Array<String>] the name of every aggregate this one points
|
|
110
|
-
# at with an aggregate-level `reference_to`
|
|
111
|
-
# @param provenance [Object, nil] the aggregate's declared canonical source, captured
|
|
112
|
-
# exactly as written, or `nil` if it declares none
|
|
46
|
+
# Assigns the declared fields, then `settle` derives identity, name indexes and owner stamps.
|
|
113
47
|
def initialize(name:, description: nil, attributes: [], value_objects: [],
|
|
114
48
|
commands: [], invariants: [], preconditions: [], projected_fields: [], identified_by: [], lifecycle: nil,
|
|
115
49
|
entities: [], queries: [], policies: [], ports: [], reference_targets: [],
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
class Assembly
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
# The fields come from the contract like every other construct's. What is here
|
|
7
|
-
# is the part no field table can say: which construct holds which, and how a
|
|
8
|
-
# head's references become able to resolve.
|
|
9
|
-
#
|
|
10
|
-
# It decides nothing. Whether a declaration is admissible was settled on the
|
|
11
|
-
# way in, by the language.
|
|
4
|
+
# Builds one aggregate from its declaration: containment and reference resolution.
|
|
12
5
|
class AggregateAssembly
|
|
13
6
|
# @param row [Hash{Symbol => Object}] one declared aggregate's raw contract data,
|
|
14
7
|
# as `@declaration[:aggregates]` carries it
|
|
@@ -36,10 +29,7 @@ module Hecks
|
|
|
36
29
|
entities: entities,
|
|
37
30
|
queries: asks,
|
|
38
31
|
lifecycle: lifecycle_of(@row),
|
|
39
|
-
#
|
|
40
|
-
# builder, and `Aggregate#to_h` never carried it — so the language does
|
|
41
|
-
# not record which head a chapter-level policy was written in. The
|
|
42
|
-
# chapter holds them all, which is what `PolicyInterpreter` reads.
|
|
32
|
+
# Policies live on the chapter, which is what `PolicyInterpreter` reads.
|
|
43
33
|
policies: [],
|
|
44
34
|
reference_targets: reference_targets(fields)
|
|
45
35
|
)
|
|
@@ -50,12 +40,7 @@ module Hecks
|
|
|
50
40
|
|
|
51
41
|
private
|
|
52
42
|
|
|
53
|
-
#
|
|
54
|
-
# self-references its verbs carry — the first version read
|
|
55
|
-
# `commands.filter_map(&:references)` and gave Pizza two targets of "Pizza",
|
|
56
|
-
# its own verbs pointing at itself, where the builder recorded none. An
|
|
57
|
-
# aggregate-level `reference_to X` leaves a reference attribute behind, so
|
|
58
|
-
# the attributes are where the answer is.
|
|
43
|
+
# Read from attributes, not commands: a command's self-references are not targets.
|
|
59
44
|
def reference_targets(fields)
|
|
60
45
|
fields.select(&:reference?).map { |field| field.type.target_name }
|
|
61
46
|
end
|
|
@@ -64,12 +49,7 @@ module Hecks
|
|
|
64
49
|
Build.call("ValueObject", row)
|
|
65
50
|
end
|
|
66
51
|
|
|
67
|
-
#
|
|
68
|
-
# `entity` is declared by the language and used zero times in it"
|
|
69
|
-
# — Dispatch, inside Handler, is the first use, so `row[:entities]`
|
|
70
|
-
# is built the same way `row` itself was reached: through this
|
|
71
|
-
# same method, one level deeper each time. Nothing here assumes
|
|
72
|
-
# it stops at one level of nesting.
|
|
52
|
+
# Recurses, so entities nest to any depth (ADR 0026).
|
|
73
53
|
def entity(row)
|
|
74
54
|
Build.call(
|
|
75
55
|
"Entity", row,
|
|
@@ -80,10 +60,8 @@ module Hecks
|
|
|
80
60
|
)
|
|
81
61
|
end
|
|
82
62
|
|
|
83
|
-
#
|
|
84
|
-
# and
|
|
85
|
-
# reference the walk misses resolves to nil, and a nil target is skipped
|
|
86
|
-
# rather than refused, so the guarantee would go quiet instead of red.
|
|
63
|
+
# Must cover every list that can carry a reference: a missed one resolves to nil,
|
|
64
|
+
# and a nil target is skipped rather than refused.
|
|
87
65
|
def stamp_references(aggregate)
|
|
88
66
|
lists = [aggregate.attributes, *aggregate.commands.map(&:attributes), *aggregate.queries.map(&:attributes)]
|
|
89
67
|
entity_reference_lists(aggregate.entities, lists)
|
|
@@ -91,8 +69,6 @@ module Hecks
|
|
|
91
69
|
lists.flatten.select(&:reference?).each { |field| field.type.declared_in = aggregate }
|
|
92
70
|
end
|
|
93
71
|
|
|
94
|
-
# S17, ADR 0026 — walks nested entities too (Dispatch, inside
|
|
95
|
-
# Handler), not only an aggregate's own direct ones.
|
|
96
72
|
def entity_reference_lists(entities, lists)
|
|
97
73
|
entities.each do |piece|
|
|
98
74
|
lists << piece.attributes
|
|
@@ -102,9 +78,7 @@ module Hecks
|
|
|
102
78
|
end
|
|
103
79
|
end
|
|
104
80
|
|
|
105
|
-
#
|
|
106
|
-
# `transitions` are separate declarations; the IR keeps one Lifecycle. The
|
|
107
|
-
# contract names them derived, and this is what derives them.
|
|
81
|
+
# Folds `state_field`, `state_start` and `transitions` into the IR's one Lifecycle.
|
|
108
82
|
def lifecycle_of(row)
|
|
109
83
|
declared = row[:lifecycle]
|
|
110
84
|
return nil unless declared
|
|
@@ -116,11 +90,8 @@ module Hecks
|
|
|
116
90
|
)
|
|
117
91
|
end
|
|
118
92
|
|
|
119
|
-
#
|
|
120
|
-
#
|
|
121
|
-
# target, because one declared pair has exactly one target and may have many
|
|
122
|
-
# froms — grouping by command alone would fuse two declarations that move the
|
|
123
|
-
# same verb to different states.
|
|
93
|
+
# Regroups `to_h` rows by command and target; grouping by command alone would fuse
|
|
94
|
+
# declarations that move one verb to different states.
|
|
124
95
|
def transitions(rows)
|
|
125
96
|
rows.group_by { |move| [move[:command], move[:to_state]] }
|
|
126
97
|
.map do |(command, target), moves|
|
|
@@ -1,18 +1,9 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
3
|
class Assembly
|
|
4
|
-
#
|
|
4
|
+
# Builds any construct from its declared row by reading its `Assembly.contract`.
|
|
5
5
|
#
|
|
6
|
-
#
|
|
7
|
-
# `policy(row)`, each gathering the same keywords the contract already
|
|
8
|
-
# names. This reads the contract instead, so adding a field to the
|
|
9
|
-
# language and forgetting to assemble it is caught by the coverage gate
|
|
10
|
-
# rather than by nobody.
|
|
11
|
-
#
|
|
12
|
-
# `make` is the only branch, and it is a real one: a construct that became a
|
|
13
|
-
# class is `.declare`d, an instance is `.new`ed. That is the boundary
|
|
14
|
-
# `Query` sits on, and it is a fact about Ruby rather than about the
|
|
15
|
-
# domain.
|
|
6
|
+
# A construct that is a class is `.declare`d; an instance is `.new`ed.
|
|
16
7
|
module Build
|
|
17
8
|
module_function
|
|
18
9
|
|
|
@@ -42,8 +33,7 @@ module Hecks
|
|
|
42
33
|
contract.holder or raise ArgumentError, "#{contract} holds nothing that can be built"
|
|
43
34
|
end
|
|
44
35
|
|
|
45
|
-
#
|
|
46
|
-
# need no decoding at all.
|
|
36
|
+
# Reads one value through a contract reader.
|
|
47
37
|
#
|
|
48
38
|
# @param reader [Symbol, Array, nil] the contract field's reader: `:plain`,
|
|
49
39
|
# `:identity`, `:flag`, `[:each, marks_method]`, `[:option, name]`, or a bare
|
|
@@ -56,8 +46,7 @@ module Hecks
|
|
|
56
46
|
when :identity then value&.to_sym
|
|
57
47
|
when :flag then value ? true : false
|
|
58
48
|
when Array
|
|
59
|
-
# [:
|
|
60
|
-
# which needs its name as well as its value.
|
|
49
|
+
# `[:option, name]` needs its name as well as its value.
|
|
61
50
|
if reader.first == :each
|
|
62
51
|
Array(value).map { |held| Marks.public_send(reader.last, held) }
|
|
63
52
|
else
|
|
@@ -1,94 +1,26 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# struct format itself (this file) plus, reopened in contracts.rb, the
|
|
6
|
-
# `CONTRACTS` table of one `Contract` per construct category.
|
|
3
|
+
# Translates the language's declarations into the IR that `Build` and
|
|
4
|
+
# `Reconstruction` produce; `CONTRACTS` (contracts.rb) holds one per category.
|
|
7
5
|
class Assembly
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
#
|
|
11
|
-
# Naming a field derived is a claim, and a claim needs a kind, not just a name
|
|
12
|
-
# in a list. A bare list of names is a promise with nobody holding it: the
|
|
13
|
-
# coverage gate only asks whether a field is accounted for, so `derived:
|
|
14
|
-
# %i[version]` would satisfy it while dropping a chapter's version in
|
|
15
|
-
# silence — the exact shape of every defect this arc has found.
|
|
16
|
-
#
|
|
17
|
-
# :parent the containment tree supplies it — a `*_id`, or one of
|
|
18
|
-
# the named pointers below. Checked against the name.
|
|
19
|
-
# :children it is assembled as child constructs. Checked against the
|
|
20
|
-
# language: a category must exist whose parent is this one.
|
|
21
|
-
# [:computed, :m] the holder works it out. Checked: it must answer to `m`.
|
|
22
|
-
# [:folded, keys] several language fields are one thing in the IR, or one
|
|
23
|
-
# is spread across several. Checked: every key must appear
|
|
24
|
-
# in a real reconstructed declaration.
|
|
25
|
-
# :elsewhere not a fact about this construct at all. Allow-listed one
|
|
26
|
-
# by one, because it is the kind with no other check.
|
|
27
|
-
#
|
|
28
|
-
# Every one of those can fail. That is the whole difference.
|
|
6
|
+
# A derived claim's kind is one of :parent, :children, [:computed, method],
|
|
7
|
+
# [:folded, keys], or :elsewhere — each checked structurally, not just named.
|
|
29
8
|
Contract = Struct.new(:holder, :make, :fields, :derived, :rows, :reads, keyword_init: true) do
|
|
30
|
-
#
|
|
31
|
-
# `text(row[key])`, a single cell — which is most of them ; present names the
|
|
32
|
-
# shape, because a list needs a reader per element and a folded field is
|
|
33
|
-
# gathered rather than fetched. Same pattern as `rows`, in the other
|
|
34
|
-
# direction: declare the exceptions, default the rest.
|
|
35
|
-
#
|
|
36
|
-
# @param key [String, Symbol] the field's declaration key, as `fields` names it
|
|
37
|
-
# @return [Symbol, Array, nil] the reader named in `reads` for `key`, or `nil`
|
|
38
|
-
# when the field reads through the default single-cell reader
|
|
9
|
+
# nil means the field reads through the default single-cell reader.
|
|
39
10
|
def reader(key) = Hash(reads)[key.to_sym]
|
|
40
11
|
|
|
41
|
-
#
|
|
42
|
-
# here reads straight off the node ; one that is present names the shaper,
|
|
43
|
-
# because the IR keeps a shape the language does not — a transition whose
|
|
44
|
-
# `from` is a list is several rows, an append binds several fields at once,
|
|
45
|
-
# an open map is one row per entry.
|
|
46
|
-
#
|
|
47
|
-
# @param list [String, Symbol] the appendable list's field name
|
|
48
|
-
# @return [Symbol, nil] the shaper method named in `rows` for `list`, or `nil`
|
|
49
|
-
# when the list reads straight off the node instead
|
|
12
|
+
# nil means the list reads straight off the node.
|
|
50
13
|
def shaper(list) = Hash(rows)[list.to_sym]
|
|
51
14
|
|
|
52
|
-
# Whether `field` is one this contract accounts for, stored or derived.
|
|
53
|
-
#
|
|
54
|
-
# @param field [Symbol] the field name to check
|
|
55
|
-
# @return [Boolean] whether `field` is a key of `fields` or of `derived`
|
|
56
15
|
def declares?(field) = fields.key?(field) || derived.key?(field)
|
|
57
16
|
|
|
58
|
-
# Names the kind of derived claim `field` makes, if any.
|
|
59
|
-
#
|
|
60
|
-
# @param field [Symbol] the derived field name to check
|
|
61
|
-
# @return [Symbol, Array, nil] the kind `derived` names for `field` — `:parent`,
|
|
62
|
-
# `:children`, `:elsewhere`, `:walk`, an `[:computed, method]` or `[:folded,
|
|
63
|
-
# object, member]` pair — or `nil` when `field` is not derived
|
|
64
17
|
def kind_of(field) = derived[field]
|
|
65
18
|
|
|
66
|
-
#
|
|
67
|
-
# The language declares them (`attribute :position, Position`) so the
|
|
68
|
-
# judge can order siblings, but no constructor takes one. This is the one
|
|
69
|
-
# place that fact is stated ; `Specializer` and `Model::Deviations` read it
|
|
70
|
-
# here rather than each keeping their own `%i[position]`.
|
|
71
|
-
#
|
|
72
|
-
# @return [Array<Symbol>] every field name whose derived kind is `:walk`
|
|
19
|
+
# Every derived field the walk supplies; Specializer skips these.
|
|
73
20
|
def walked = derived.select { |_field, kind| kind == :walk }.keys
|
|
74
21
|
|
|
75
|
-
#
|
|
76
|
-
#
|
|
77
|
-
# `[:folded, :lifecycle, :field]` says the language's `state_field` is the
|
|
78
|
-
# `field` of the IR's one Lifecycle. `Readings` would otherwise have to state
|
|
79
|
-
# that fact a second time as `node.lifecycle&.field` — saying it once here
|
|
80
|
-
# drives both directions instead: the walk reads the member on the way in, and
|
|
81
|
-
# the reconstruction gathers the members back into the object on the way out.
|
|
82
|
-
#
|
|
83
|
-
# A nil member means the fold has no single member to name — `rows` is a
|
|
84
|
-
# count of what `closed_set` and `members` hold between them, and `options`
|
|
85
|
-
# spreads across eight keys. Those keep their own code, and the gate still
|
|
86
|
-
# checks the object they name is real.
|
|
87
|
-
#
|
|
88
|
-
# @param field [Symbol] the derived field name to check
|
|
89
|
-
# @return [Array(Symbol, Symbol), Array(Array<Symbol>, nil), nil] the `[object,
|
|
90
|
-
# member]` pair the field folds into — `member` is `nil` when the fold has
|
|
91
|
-
# no single member to name — or `nil` when `field` does not fold at all
|
|
22
|
+
# [object, member] a folded field lives at; member is nil when the fold
|
|
23
|
+
# has no single one to name (e.g. a count plus a list of rows).
|
|
92
24
|
def folded(field)
|
|
93
25
|
kind = derived[field]
|
|
94
26
|
return nil unless kind.is_a?(Array) && kind.first == :folded
|
|
@@ -96,20 +28,8 @@ module Hecks
|
|
|
96
28
|
[kind[1], kind[2]]
|
|
97
29
|
end
|
|
98
30
|
|
|
99
|
-
# Computed means
|
|
100
|
-
#
|
|
101
|
-
# Asking only whether the holder responds was too weak, and measurably so:
|
|
102
|
-
# `[:computed, :version]` passed, because `Bluebook` does answer to
|
|
103
|
-
# `version` — it just answers with what the constructor was handed. A field
|
|
104
|
-
# the constructor takes is stored, and calling it computed is how a chapter's
|
|
105
|
-
# version would have gone missing while the gate said yes.
|
|
106
|
-
#
|
|
107
|
-
# So a computed field is one the holder answers and the constructor does not
|
|
108
|
-
# accept. `query_name` qualifies (`Naming.snake(name)`) ; `version` cannot.
|
|
109
|
-
#
|
|
110
|
-
# @param method [Symbol] the field name to check
|
|
111
|
-
# @return [Boolean] whether `holder` answers `method` but its constructor does
|
|
112
|
-
# not accept it as a keyword
|
|
31
|
+
# Computed means the holder answers but its constructor won't accept it —
|
|
32
|
+
# respond_to? alone would also count a stored field like `version`.
|
|
113
33
|
def computes?(method)
|
|
114
34
|
return false unless holder
|
|
115
35
|
return false unless answers?(method)
|
|
@@ -117,22 +37,10 @@ module Hecks
|
|
|
117
37
|
!accepts?(method)
|
|
118
38
|
end
|
|
119
39
|
|
|
120
|
-
# Whether `holder` answers `method`, checked the way that fits how it is
|
|
121
|
-
# built: `respond_to?` for a `:declare` holder (a class, queried live) and
|
|
122
|
-
# `method_defined?` for a `:new` holder (an instance method, checked without
|
|
123
|
-
# building one).
|
|
124
|
-
#
|
|
125
|
-
# @param method [Symbol] the method name to check
|
|
126
|
-
# @return [Boolean] whether `holder` answers `method`
|
|
127
40
|
def answers?(method)
|
|
128
41
|
make == :declare ? holder.respond_to?(method) : holder.method_defined?(method)
|
|
129
42
|
end
|
|
130
43
|
|
|
131
|
-
# Whether the holder's constructor takes `keyword` as a keyword argument.
|
|
132
|
-
#
|
|
133
|
-
# @param keyword [Symbol] the keyword to check
|
|
134
|
-
# @return [Boolean] whether the holder's constructor (`.declare` or
|
|
135
|
-
# `#initialize`) accepts `keyword` as an optional or required keyword
|
|
136
44
|
def accepts?(keyword)
|
|
137
45
|
builder = make == :declare ? holder.method(:declare) : holder.instance_method(:initialize)
|
|
138
46
|
|
|
@@ -140,49 +48,20 @@ module Hecks
|
|
|
140
48
|
end
|
|
141
49
|
end
|
|
142
50
|
|
|
143
|
-
#
|
|
144
|
-
#
|
|
145
|
-
# QueryIR (a declared field the model composes instead of storing).
|
|
146
|
-
#
|
|
147
|
-
# aggregate, bluebook the bare parent link a creating command mints
|
|
148
|
-
# (ADR 0025) — exactly the `parent_key`s `Plan` reads
|
|
149
|
-
# off the language
|
|
150
|
-
# owner Entity's own text twin of that link, which is why
|
|
151
|
-
# Entity's contract claims `owner: :parent`
|
|
152
|
-
#
|
|
153
|
-
# `shape` and `handler` are not on this list — S17 (ADR 0026) made Member and
|
|
154
|
-
# Dispatch nested entities, so neither is a parent field the way
|
|
155
|
-
# `owner` is. `spec/assembly_spec` derives this set from `Plan` and the
|
|
156
|
-
# contracts directly and fails on any drift, rather than trusting this list to
|
|
157
|
-
# stay in sync with a second hand-written copy kept by the model generator.
|
|
51
|
+
# Parent-pointer fields that don't end in `_id` (ADR 0025).
|
|
52
|
+
# spec/assembly_spec derives this set independently and fails on drift.
|
|
158
53
|
PARENT_POINTERS = %i[aggregate bluebook owner].freeze
|
|
159
54
|
|
|
160
|
-
# Whether `field` is a parent pointer that does not end in `_id`.
|
|
161
|
-
#
|
|
162
|
-
# @param field [String, Symbol] the field name to check
|
|
163
|
-
# @return [Boolean] whether `field` ends with `_id`, or is one of
|
|
164
|
-
# `PARENT_POINTERS`
|
|
165
55
|
def self.parent_pointer?(field)
|
|
166
56
|
field.to_s.end_with?("_id") || PARENT_POINTERS.include?(field.to_sym)
|
|
167
57
|
end
|
|
168
58
|
|
|
169
|
-
#
|
|
170
|
-
#
|
|
171
|
-
#
|
|
172
|
-
# normalisations the canonical-form table belongs to the expression grammar.
|
|
173
|
-
# A chapter's rules are canonicalised on the way in, so the
|
|
174
|
-
# language models the table — but no chapter stores one, and
|
|
175
|
-
# `Bluebook#to_h` splices it in from Expression.
|
|
59
|
+
# Fields allowed to describe something other than their own construct.
|
|
60
|
+
# `Bluebook.normalisations` belongs to the expression grammar; `to_h` splices it in.
|
|
176
61
|
ELSEWHERE = {
|
|
177
62
|
Bluebook: %i[normalisations]
|
|
178
63
|
}.freeze
|
|
179
64
|
|
|
180
|
-
# Whether `field` is allow-listed as describing something other than
|
|
181
|
-
# `category`'s own construct — see `ELSEWHERE`.
|
|
182
|
-
#
|
|
183
|
-
# @param category [String, Symbol] the construct category name
|
|
184
|
-
# @param field [Symbol] the field name to check
|
|
185
|
-
# @return [Boolean] whether `field` is on `category`'s `ELSEWHERE` entry
|
|
186
65
|
def self.elsewhere?(category, field)
|
|
187
66
|
Array(ELSEWHERE[category.to_sym]).include?(field)
|
|
188
67
|
end
|