hecks 2.7.0 → 2.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/exe/hecks +11 -0
- data/lib/hecks/adapters/driven/claude_code.rb +4 -104
- data/lib/hecks/adapters/driven/d1.rb +44 -237
- data/lib/hecks/adapters/driven/folder.rb +17 -76
- data/lib/hecks/adapters/driven/google_authentication.rb +15 -49
- data/lib/hecks/adapters/driven/governance_authorization.rb +23 -70
- data/lib/hecks/adapters/driven/heki/journal.rb +8 -41
- data/lib/hecks/adapters/driven/heki/saga_store.rb +12 -54
- data/lib/hecks/adapters/driven/heki/snapshot.rb +4 -12
- data/lib/hecks/adapters/driven/heki.rb +13 -42
- data/lib/hecks/adapters/driven/identity_registry.rb +3 -14
- data/lib/hecks/adapters/driven/in_memory_ordering.rb +9 -26
- data/lib/hecks/adapters/driven/in_process_key_vault.rb +2 -14
- data/lib/hecks/adapters/driven/lambda/client.rb +10 -51
- data/lib/hecks/adapters/driven/lambda.rb +10 -84
- data/lib/hecks/adapters/driven/local_storage.rb +5 -40
- data/lib/hecks/adapters/driven/memory.rb +18 -99
- data/lib/hecks/adapters/driven/mock_stripe_adapter.rb +5 -21
- data/lib/hecks/adapters/driven/postgres/codec.rb +6 -28
- data/lib/hecks/adapters/driven/postgres/outbox.rb +3 -12
- data/lib/hecks/adapters/driven/postgres/reconnect.rb +4 -30
- data/lib/hecks/adapters/driven/postgres/schema_builder.rb +34 -108
- data/lib/hecks/adapters/driven/postgres.rb +145 -134
- data/lib/hecks/adapters/driven/postgres_era.adapter +4 -15
- data/lib/hecks/adapters/driven/prism.rb +7 -30
- data/lib/hecks/adapters/driven/sql_query_builder.rb +21 -121
- data/lib/hecks/adapters/driven/sqlite/codec.rb +8 -40
- data/lib/hecks/adapters/driven/sqlite/projection.rb +26 -82
- data/lib/hecks/adapters/driven/sqlite/schema_builder.rb +40 -84
- data/lib/hecks/adapters/driven/sqlite.rb +128 -65
- data/lib/hecks/adapters/driven/tenant_provisioner.rb +15 -37
- data/lib/hecks/adapters/driven.rb +5 -36
- data/lib/hecks/adapters/driving/github_webhook.rb +8 -76
- data/lib/hecks/behaviors/dsl.rb +7 -25
- data/lib/hecks/behaviors/expectations.rb +32 -142
- data/lib/hecks/behaviors/ir.rb +7 -20
- data/lib/hecks/behaviors/rspec.rb +6 -17
- data/lib/hecks/behaviors/runner.rb +10 -34
- data/lib/hecks/behaviors.rb +4 -8
- data/lib/hecks/bluebook/aggregate.rb +9 -75
- data/lib/hecks/bluebook/assembly/aggregate_assembly.rb +9 -38
- data/lib/hecks/bluebook/assembly/build.rb +4 -15
- data/lib/hecks/bluebook/assembly/contract.rb +15 -136
- data/lib/hecks/bluebook/assembly/contracts.rb +54 -174
- data/lib/hecks/bluebook/assembly/marks.rb +31 -223
- data/lib/hecks/bluebook/assembly/specializer.rb +6 -52
- data/lib/hecks/bluebook/assembly.rb +6 -45
- data/lib/hecks/bluebook/attribute.rb +12 -61
- data/lib/hecks/bluebook/behaviour/aggregate.rb +10 -39
- data/lib/hecks/bluebook/behaviour/attribute.rb +3 -14
- data/lib/hecks/bluebook/behaviour/chapter.rb +17 -42
- data/lib/hecks/bluebook/behaviour/command.rb +14 -66
- data/lib/hecks/bluebook/behaviour/domain_port.rb +4 -20
- data/lib/hecks/bluebook/behaviour/entity.rb +7 -27
- data/lib/hecks/bluebook/behaviour/hexagon.rb +23 -41
- data/lib/hecks/bluebook/behaviour/lifecycle.rb +15 -40
- data/lib/hecks/bluebook/behaviour/policy.rb +23 -52
- data/lib/hecks/bluebook/behaviour/process_manager.rb +30 -57
- data/lib/hecks/bluebook/behaviour/read_model.rb +38 -26
- data/lib/hecks/bluebook/behaviour/traits.rb +27 -64
- data/lib/hecks/bluebook/behaviour/value_object.rb +5 -24
- data/lib/hecks/bluebook/capabilities.rb +17 -49
- data/lib/hecks/bluebook/chapter.rb +10 -48
- data/lib/hecks/bluebook/command.rb +23 -81
- data/lib/hecks/bluebook/domain_port.rb +14 -63
- data/lib/hecks/bluebook/dsl/aggregate_builder/sealing.rb +50 -229
- data/lib/hecks/bluebook/dsl/aggregate_builder.rb +50 -377
- data/lib/hecks/bluebook/dsl/attribute_collector.rb +33 -204
- data/lib/hecks/bluebook/dsl/binding_proxy.rb +17 -65
- data/lib/hecks/bluebook/dsl/bluebook_builder/validation.rb +86 -708
- data/lib/hecks/bluebook/dsl/bluebook_builder.rb +56 -170
- data/lib/hecks/bluebook/dsl/bootstrap_table.rb +1 -0
- data/lib/hecks/bluebook/dsl/command_builder.rb +74 -546
- data/lib/hecks/bluebook/dsl/const_shim.rb +8 -41
- data/lib/hecks/bluebook/dsl/domain_port_builder.rb +12 -87
- data/lib/hecks/bluebook/dsl/entity_builder.rb +44 -330
- data/lib/hecks/bluebook/dsl/generic_dispatch.rb +20 -269
- data/lib/hecks/bluebook/dsl/hecksagon_builder.rb +26 -189
- data/lib/hecks/bluebook/dsl/identity_declaration.rb +13 -88
- data/lib/hecks/bluebook/dsl/lifecycle_builder.rb +6 -20
- data/lib/hecks/bluebook/dsl/policy_builder.rb +16 -88
- data/lib/hecks/bluebook/dsl/port_builder.rb +2 -6
- data/lib/hecks/bluebook/dsl/port_operation_builder.rb +22 -96
- data/lib/hecks/bluebook/dsl/process_manager_builder.rb +31 -184
- data/lib/hecks/bluebook/dsl/query_builder.rb +11 -42
- data/lib/hecks/bluebook/dsl/read_model_builder.rb +75 -201
- data/lib/hecks/bluebook/dsl/rule_reference.rb +22 -163
- data/lib/hecks/bluebook/dsl/translation_builder.rb +28 -114
- data/lib/hecks/bluebook/dsl/value_object_builder.rb +10 -124
- data/lib/hecks/bluebook/dsl/word_gate.rb +16 -162
- data/lib/hecks/bluebook/dsl/world_builder.rb +19 -106
- data/lib/hecks/bluebook/entity.rb +13 -71
- data/lib/hecks/bluebook/expression/ast_json.rb +24 -190
- data/lib/hecks/bluebook/expression/ast_reader.rb +12 -54
- data/lib/hecks/bluebook/expression/canonical_form.rb +11 -88
- data/lib/hecks/bluebook/expression/evaluator.rb +47 -295
- data/lib/hecks/bluebook/expression/resolver/block_predicates.rb +30 -147
- data/lib/hecks/bluebook/expression/resolver.rb +37 -660
- data/lib/hecks/bluebook/hexagon.rb +5 -28
- data/lib/hecks/bluebook/lifecycle.rb +5 -16
- data/lib/hecks/bluebook/meta_validator/adapter_judge.rb +1 -7
- data/lib/hecks/bluebook/meta_validator/judge.rb +111 -361
- data/lib/hecks/bluebook/meta_validator/plan.rb +33 -162
- data/lib/hecks/bluebook/meta_validator/port_judge.rb +2 -7
- data/lib/hecks/bluebook/meta_validator/readings.rb +56 -342
- data/lib/hecks/bluebook/meta_validator/reconstruction.rb +24 -176
- data/lib/hecks/bluebook/meta_validator/shapes.rb +54 -268
- data/lib/hecks/bluebook/meta_validator/syntax_boot.rb +47 -308
- data/lib/hecks/bluebook/meta_validator/translation_judge.rb +7 -43
- data/lib/hecks/bluebook/meta_validator/world_judge.rb +6 -18
- data/lib/hecks/bluebook/meta_validator.rb +79 -349
- data/lib/hecks/bluebook/model_check/client_profile.rb +10 -91
- data/lib/hecks/bluebook/model_check.rb +102 -600
- data/lib/hecks/bluebook/pattern_subset.rb +11 -69
- data/lib/hecks/bluebook/process_manager.rb +13 -83
- data/lib/hecks/bluebook/project_loader.rb +3 -39
- data/lib/hecks/bluebook/project_register.rb +12 -60
- data/lib/hecks/bluebook/query.rb +9 -48
- data/lib/hecks/bluebook/read_model.rb +57 -81
- data/lib/hecks/bluebook/reference.rb +7 -41
- data/lib/hecks/bluebook/smoke_test.rb +8 -98
- data/lib/hecks/bluebook/synthesizer.rb +13 -62
- data/lib/hecks/bluebook/translation.rb +26 -62
- data/lib/hecks/bluebook/value_object.rb +11 -36
- data/lib/hecks/bluebook.rb +5 -22
- data/lib/hecks/cache_dir.rb +84 -0
- data/lib/hecks/cli/document.rb +86 -0
- data/lib/hecks/cli/ir.rb +45 -0
- data/lib/hecks/cli/mcp.rb +31 -0
- data/lib/hecks/cli/mcp_door.rb +366 -0
- data/lib/hecks/cli/model_check.rb +203 -0
- data/lib/hecks/cli/project_cli.rb +90 -0
- data/lib/hecks/cli/project_diagrams.rb +36 -0
- data/lib/hecks/cli/run.rb +173 -0
- data/lib/hecks/cli/smoke_test.rb +45 -0
- data/lib/hecks/cli/stores.rb +53 -0
- data/lib/hecks/cli.rb +160 -0
- data/lib/hecks/construct.rb +8 -34
- data/lib/hecks/deploy/bluebook/deploy.bluebook +33 -142
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +2 -9
- data/lib/hecks/embryonaut_bluebook/lock.rb +3 -35
- data/lib/hecks/embryonaut_bluebook/shape.rb +1 -17
- data/lib/hecks/embryonaut_bluebook/vendor.rb +8 -53
- data/lib/hecks/embryonaut_bluebook/vendor_cli.rb +4 -19
- data/lib/hecks/embryonaut_bluebook.rb +4 -71
- data/lib/hecks/facade/cli_door.rb +24 -106
- data/lib/hecks/facade/cli_runner.rb +28 -172
- data/lib/hecks/facade/command_request.rb +13 -33
- data/lib/hecks/facade/handle.rb +34 -121
- data/lib/hecks/facade/json_door.rb +31 -146
- data/lib/hecks/facade/surface/aggregate_door.rb +39 -104
- data/lib/hecks/facade/surface/chapter.rb +10 -54
- data/lib/hecks/facade/surface.rb +8 -23
- data/lib/hecks/facade.rb +10 -25
- data/lib/hecks/forms/app.rb +15 -70
- data/lib/hecks/forms/command_form_renderer.rb +10 -29
- data/lib/hecks/forms/field_renderer.rb +17 -156
- data/lib/hecks/forms/field_shape.rb +30 -222
- data/lib/hecks/forms/html.rb +12 -47
- data/lib/hecks/forms/index_renderer.rb +1 -4
- data/lib/hecks/forms/page.rb +3 -9
- data/lib/hecks/forms/params.rb +14 -60
- data/lib/hecks/forms/port_argument.rb +2 -19
- data/lib/hecks/forms/query_form_renderer.rb +4 -79
- data/lib/hecks/forms/record_renderer.rb +8 -75
- data/lib/hecks/forms/record_table.rb +7 -50
- data/lib/hecks/forms/reference_options.rb +3 -30
- data/lib/hecks/forms/value_object_shape.rb +8 -35
- data/lib/hecks/forms.rb +5 -33
- data/lib/hecks/fqn.rb +5 -12
- data/lib/hecks/framework/bluebook/compliance.bluebook +16 -65
- data/lib/hecks/framework/bluebook/console_settings.bluebook +47 -134
- data/lib/hecks/framework/bluebook/framework.hecksagon +5 -14
- data/lib/hecks/framework/bluebook/governance.bluebook +13 -34
- data/lib/hecks/framework/bluebook/identity.bluebook +11 -26
- data/lib/hecks/framework/bluebook/privacy.bluebook +8 -33
- data/lib/hecks/framework.rb +11 -80
- data/lib/hecks/freezer.rb +5 -39
- data/lib/hecks/grammar/expression.bluebook +15 -40
- data/lib/hecks/grammar/translation.bluebook +3 -6
- data/lib/hecks/grammar.rb +16 -41
- data/lib/hecks/ir.rb +14 -83
- data/lib/hecks/language/adapter.bluebook +2 -7
- data/lib/hecks/language/bluebook/aggregate.bluebook +56 -221
- data/lib/hecks/language/bluebook/attaches/paging.bluebook +6 -15
- data/lib/hecks/language/bluebook/bluebook.bluebook +15 -83
- data/lib/hecks/language/bluebook/bluebook.hecksagon +3 -15
- data/lib/hecks/language/bluebook/command.bluebook +27 -144
- data/lib/hecks/language/bluebook/entity.bluebook +24 -97
- data/lib/hecks/language/bluebook/policy.bluebook +16 -67
- data/lib/hecks/language/bluebook/process_manager.bluebook +28 -151
- data/lib/hecks/language/bluebook/projection.bluebook +126 -60
- data/lib/hecks/language/bluebook/query.bluebook +12 -43
- data/lib/hecks/language/bluebook/shape.bluebook +23 -73
- data/lib/hecks/language/bluebook/syntax.bluebook +51 -262
- data/lib/hecks/language/bluebook/vocabulary.bluebook +98 -197
- data/lib/hecks/language/hecksagon/adapter_binding.bluebook +3 -10
- data/lib/hecks/language/hecksagon/domain_port.bluebook +4 -19
- data/lib/hecks/language/hecksagon/hecksagon.bluebook +6 -25
- data/lib/hecks/language/hecksagon/port_operation.bluebook +3 -14
- data/lib/hecks/language/oidc.json +35 -0
- data/lib/hecks/language/port.bluebook +4 -17
- data/lib/hecks/language/translation/translation.bluebook +3 -9
- data/lib/hecks/language/translation/translation_aggregate.bluebook +5 -24
- data/lib/hecks/language/world/wiring.bluebook +1 -3
- data/lib/hecks/language/world/world.bluebook +5 -7
- data/lib/hecks/literal.rb +8 -50
- data/lib/hecks/mcp_door_scope.rb +95 -0
- data/lib/hecks/mcp_stdio_guard.rb +4 -41
- data/lib/hecks/naming.rb +29 -137
- data/lib/hecks/ports/access_control.rb +7 -23
- data/lib/hecks/ports/agent/answers.rb +5 -23
- data/lib/hecks/ports/agent.rb +47 -172
- data/lib/hecks/ports/authentication.rb +12 -39
- data/lib/hecks/ports/authorization.rb +16 -43
- data/lib/hecks/ports/clock.rb +5 -45
- data/lib/hecks/ports/extraction.rb +7 -12
- data/lib/hecks/ports/identity_assignment.rb +8 -29
- data/lib/hecks/ports/identity_generation.rb +6 -29
- data/lib/hecks/ports/identity_resolution.rb +2 -10
- data/lib/hecks/ports/key_vault.rb +9 -45
- data/lib/hecks/ports/persistence/append_only.rb +62 -65
- data/lib/hecks/ports/persistence/binding_policy.rb +4 -14
- data/lib/hecks/ports/persistence/codec_boundary.rb +20 -80
- data/lib/hecks/ports/persistence/null_saga_store.rb +4 -20
- data/lib/hecks/ports/persistence/plugin.rb +13 -42
- data/lib/hecks/ports/persistence/plugins/era/era_check.rb +38 -141
- data/lib/hecks/ports/persistence/plugins/era/era_guard/shape_diff.rb +15 -115
- data/lib/hecks/ports/persistence/plugins/era/era_guard.rb +16 -84
- data/lib/hecks/ports/persistence/plugins/era/era_tamper.rb +7 -26
- data/lib/hecks/ports/persistence/plugins/era/expected_era.rb +3 -22
- data/lib/hecks/ports/persistence/plugins/era/lineage.rb +55 -181
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/events.rb +77 -0
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/era_store.rb +12 -122
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/field_cache.rb +28 -128
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/head_compiler.rb +73 -474
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/mint_transaction.rb +31 -124
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/provisioning.rb +45 -219
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/resumable_backfill.rb +13 -108
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/tail_merge.rb +18 -75
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage/transform_installer.rb +9 -49
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage.rb +6 -123
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/coverage_check.rb +23 -55
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/era_resolver.rb +14 -72
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/merge_coordinator.rb +7 -16
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager/minter.rb +14 -115
- data/lib/hecks/ports/persistence/plugins/era/postgres_era/lineage_manager.rb +13 -45
- data/lib/hecks/ports/persistence/plugins/era/postgres_era.rb +127 -554
- data/lib/hecks/ports/persistence/plugins/era/storage_shape.rb +13 -63
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/approval_digest.rb +2 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_one.rb +3 -14
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/layer_two.rb +13 -58
- data/lib/hecks/ports/persistence/plugins/era/translation/audit/unfed_report.rb +3 -17
- data/lib/hecks/ports/persistence/plugins/era/translation/audit.rb +9 -26
- data/lib/hecks/ports/persistence/plugins/era/translation/reattest.rb +9 -25
- data/lib/hecks/ports/persistence/plugins/era/translation/rule_compiler.rb +22 -122
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/differ.rb +34 -123
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/renderer.rb +5 -12
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold/writer.rb +3 -9
- data/lib/hecks/ports/persistence/plugins/era/translation/scaffold.rb +2 -14
- data/lib/hecks/ports/persistence/plugins/era.rb +4 -23
- data/lib/hecks/ports/persistence/postgres_dump/connection.rb +7 -23
- data/lib/hecks/ports/persistence/postgres_dump.rb +4 -35
- data/lib/hecks/ports/persistence/remote_runtime.rb +2 -24
- data/lib/hecks/ports/persistence/repository_factory.rb +8 -27
- data/lib/hecks/ports/persistence/state_codec.rb +23 -103
- data/lib/hecks/ports/persistence.rb +7 -14
- data/lib/hecks/ports/projection.rb +42 -84
- data/lib/hecks/ports/query/in_memory.rb +10 -58
- data/lib/hecks/ports/query/ordering.rb +11 -32
- data/lib/hecks/ports/query.rb +14 -37
- data/lib/hecks/ports.rb +2 -8
- data/lib/hecks/projections/bootstrap_table.rb +11 -43
- data/lib/hecks/projections/deploy/fargate/assembly.rb +2 -15
- data/lib/hecks/projections/deploy/fargate/cdn.rb +1 -48
- data/lib/hecks/projections/deploy/fargate/cdn_default.rb +2 -11
- data/lib/hecks/projections/deploy/fargate/check.rb +5 -14
- data/lib/hecks/projections/deploy/fargate/containers.rb +3 -78
- data/lib/hecks/projections/deploy/fargate/extras.rb +3 -44
- data/lib/hecks/projections/deploy/fargate/monitoring.rb +0 -44
- data/lib/hecks/projections/deploy/fargate/settings.rb +2 -54
- data/lib/hecks/projections/deploy/fargate/yaml.rb +13 -58
- data/lib/hecks/projections/deploy/fargate.rb +35 -202
- data/lib/hecks/projections/deploy/lambda.rb +151 -679
- data/lib/hecks/projections/deploy/preview/access_yaml.rb +1 -33
- data/lib/hecks/projections/deploy/preview/containers.rb +6 -111
- data/lib/hecks/projections/deploy/preview/routing_yaml.rb +4 -56
- data/lib/hecks/projections/deploy/preview/script.rb +2 -14
- data/lib/hecks/projections/deploy/preview/settings.rb +3 -33
- data/lib/hecks/projections/deploy/preview/task_yaml.rb +2 -38
- data/lib/hecks/projections/deploy/preview/template.rb +2 -58
- data/lib/hecks/projections/deploy/preview.rb +2 -67
- data/lib/hecks/projections/deploy/scripts/settings.rb +3 -25
- data/lib/hecks/projections/deploy/scripts.rb +4 -57
- data/lib/hecks/projections/deploy/shared.rb +47 -146
- data/lib/hecks/projections/deploy/smoke.rb +4 -61
- data/lib/hecks/projections/deploy/template_diff/comparer.rb +3 -25
- data/lib/hecks/projections/deploy/template_diff/loader.rb +2 -11
- data/lib/hecks/projections/deploy/template_diff.rb +5 -57
- data/lib/hecks/projections/diagrams.rb +20 -582
- data/lib/hecks/projections/glossary/html.rb +14 -130
- data/lib/hecks/projections/glossary/markdown.rb +8 -69
- data/lib/hecks/projections/glossary/mermaid.rb +9 -66
- data/lib/hecks/projections/glossary/sensitivity.rb +5 -34
- data/lib/hecks/projections/glossary/sentences.rb +14 -159
- data/lib/hecks/projections/glossary.rb +30 -222
- data/lib/hecks/projections/ir.rb +3 -10
- data/lib/hecks/projections/model/deviations.rb +15 -42
- data/lib/hecks/projections/model.rb +12 -51
- data/lib/hecks/projections/oidc.rb +12 -56
- data/lib/hecks/projections/parser_table.rb +9 -28
- data/lib/hecks/projections/reference.rb +9 -16
- data/lib/hecks/projections/rust_vocabulary.rb +12 -250
- data/lib/hecks/projections/shape.rb +3 -29
- data/lib/hecks/projections/statements.rb +7 -86
- data/lib/hecks/projections/vocabulary.rb +6 -22
- data/lib/hecks/projections.rb +2 -16
- data/lib/hecks/projector/cli_projector.rb +60 -375
- data/lib/hecks/projector/docs_projector.rb +10 -201
- data/lib/hecks/projector/exporter.rb +46 -138
- data/lib/hecks/projector/ir_projector.rb +2 -9
- data/lib/hecks/projector/narrate_projector.rb +15 -189
- data/lib/hecks/projector/target.rb +13 -76
- data/lib/hecks/projector.rb +30 -121
- data/lib/hecks/query_specification/common/comparators.rb +5 -26
- data/lib/hecks/query_specification/common/comparison.rb +35 -143
- data/lib/hecks/query_specification/common/dsl.rb +8 -24
- data/lib/hecks/query_specification/common/null_policy.rb +20 -70
- data/lib/hecks/query_specification/common/options.rb +2 -6
- data/lib/hecks/query_specification/common/where_clause.rb +2 -10
- data/lib/hecks/query_specification/field_path.rb +37 -77
- data/lib/hecks/query_specification/hop_path.rb +12 -76
- data/lib/hecks/release/gem_pin.rb +2 -26
- data/lib/hecks/release/runner/ci_publisher.rb +93 -0
- data/lib/hecks/release/runner/commands.rb +66 -0
- data/lib/hecks/release/runner/console.rb +52 -0
- data/lib/hecks/release/runner/gem_publisher.rb +43 -0
- data/lib/hecks/release/runner/git.rb +48 -0
- data/lib/hecks/release/runner/npm_publisher.rb +75 -0
- data/lib/hecks/release/runner/preflight.rb +104 -0
- data/lib/hecks/release/runner/published.rb +55 -0
- data/lib/hecks/release/runner/tagger.rb +80 -0
- data/lib/hecks/release/runner.rb +215 -0
- data/lib/hecks/rendering.rb +4 -26
- data/lib/hecks/router/namespace_installer.rb +12 -36
- data/lib/hecks/router.rb +4 -8
- data/lib/hecks/runtime/aggregate_lock.rb +8 -33
- data/lib/hecks/runtime/boot_gates.rb +3 -18
- data/lib/hecks/runtime/caller.rb +19 -59
- data/lib/hecks/runtime/capability_graph.rb +5 -21
- data/lib/hecks/runtime/command_interpreter/argument_gate.rb +16 -78
- data/lib/hecks/runtime/command_interpreter/mutation_applier.rb +23 -160
- data/lib/hecks/runtime/command_interpreter.rb +125 -307
- data/lib/hecks/runtime/command_rules/admissibility.rb +95 -366
- data/lib/hecks/runtime/command_rules/arithmetic.rb +66 -196
- data/lib/hecks/runtime/command_rules/authorization.rb +13 -45
- data/lib/hecks/runtime/command_rules/emission.rb +8 -21
- data/lib/hecks/runtime/command_rules/references.rb +23 -202
- data/lib/hecks/runtime/dependency_planning.rb +30 -102
- data/lib/hecks/runtime/dispatcher.rb +82 -241
- data/lib/hecks/runtime/entity_element.rb +40 -462
- data/lib/hecks/runtime/entity_interpreter.rb +65 -220
- data/lib/hecks/runtime/errors.rb +32 -115
- data/lib/hecks/runtime/event.rb +3 -25
- data/lib/hecks/runtime/identity.rb +18 -154
- data/lib/hecks/runtime/instance.rb +18 -150
- data/lib/hecks/runtime/interpreting.rb +11 -70
- data/lib/hecks/runtime/invocation.rb +28 -164
- data/lib/hecks/runtime/loader.rb +48 -186
- data/lib/hecks/runtime/outbox.rb +38 -261
- data/lib/hecks/runtime/policy_interpreter.rb +38 -200
- data/lib/hecks/runtime/port_operation_interpreter.rb +26 -87
- data/lib/hecks/runtime/query_interpreter.rb +45 -187
- data/lib/hecks/runtime/reaction_invocation.rb +36 -138
- data/lib/hecks/runtime/read_model_interpreter.rb +139 -208
- data/lib/hecks/runtime/rebuild_sweep.rb +8 -54
- data/lib/hecks/runtime/reference_hop.rb +8 -81
- data/lib/hecks/runtime/refusal_wording.rb +8 -89
- data/lib/hecks/runtime/registry/saga_persistence.rb +10 -102
- data/lib/hecks/runtime/registry/verification.rb +52 -225
- data/lib/hecks/runtime/registry/world_defaults.rb +4 -53
- data/lib/hecks/runtime/registry.rb +103 -244
- data/lib/hecks/runtime/remote_dispatcher.rb +37 -152
- data/lib/hecks/runtime/routing.rb +4 -15
- data/lib/hecks/runtime/saga_interpreter/correlation.rb +14 -61
- data/lib/hecks/runtime/saga_interpreter.rb +79 -263
- data/lib/hecks/runtime/saga_pending_dispatch.rb +2 -43
- data/lib/hecks/runtime/tenant_check.rb +6 -68
- data/lib/hecks/runtime/tenant_scope.rb +3 -28
- data/lib/hecks/runtime/value/admission.rb +16 -67
- data/lib/hecks/runtime/value/coercion.rb +155 -641
- data/lib/hecks/runtime/value/entity_list_coercion.rb +26 -219
- data/lib/hecks/runtime/value.rb +12 -84
- data/lib/hecks/runtime.rb +17 -65
- data/lib/hecks/storehouse.rb +146 -567
- data/lib/hecks/tenancy/bluebook/tenancy.bluebook +8 -32
- data/lib/hecks/tenancy/bluebook/tenancy.hecksagon +6 -23
- data/lib/hecks/vendoring/git_environment.rb +2 -8
- data/lib/hecks/vendoring/git_source.rb +4 -10
- data/lib/hecks/vendoring.rb +7 -46
- data/lib/hecks/version.rb +3 -14
- data/lib/hecks/vocabulary.rb +5 -0
- data/lib/hecks.rb +32 -82
- data/lib/rubocop/cop/hecks/fallback_hash_lookup.rb +8 -46
- data/lib/rubocop/cop/hecks/sequential_hash_rename_in_loop.rb +11 -80
- data/lib/rubocop/cop/hecks/thread_shared_ivar_mutation.rb +10 -99
- metadata +30 -59
- data/lib/hecks/bench/cli.rb +0 -74
- data/lib/hecks/bench/environment.rb +0 -100
- data/lib/hecks/bench/postgres_probe.rb +0 -41
- data/lib/hecks/bench/report.rb +0 -116
- data/lib/hecks/bench/ruby_runner.rb +0 -151
- data/lib/hecks/bench/run.rb +0 -55
- data/lib/hecks/bench/rust_runner.rb +0 -165
- data/lib/hecks/bench/stats.rb +0 -75
- data/lib/hecks/bench/suite.rb +0 -172
- data/lib/hecks/bench/workload.rb +0 -137
- data/lib/hecks/bench.rb +0 -28
- data/lib/hecks/codemod.rb +0 -443
- data/lib/hecks/corpus.rb +0 -479
- data/lib/hecks/doc/reference.rb +0 -585
- data/lib/hecks/fuzzing/bounded_exhaustive_expressions.rb +0 -684
- data/lib/hecks/fuzzing/combination_miner.rb +0 -178
- data/lib/hecks/fuzzing/concurrent_dispatch.rb +0 -469
- data/lib/hecks/fuzzing/coverage_campaign.rb +0 -161
- data/lib/hecks/fuzzing/differential.rb +0 -192
- data/lib/hecks/fuzzing/domain_generator.rb +0 -871
- data/lib/hecks/fuzzing/era_boundary.rb +0 -154
- data/lib/hecks/fuzzing/form_census.rb +0 -285
- data/lib/hecks/fuzzing/generated_domain_check.rb +0 -171
- data/lib/hecks/fuzzing/invalid_value_generator.rb +0 -125
- data/lib/hecks/fuzzing/isolated_boot.rb +0 -658
- data/lib/hecks/fuzzing/nondeterministic.rb +0 -79
- data/lib/hecks/fuzzing/persistence_parity.rb +0 -253
- data/lib/hecks/fuzzing/properties/corrections.rb +0 -125
- data/lib/hecks/fuzzing/properties/dispatch_and_mutations.rb +0 -688
- data/lib/hecks/fuzzing/properties/guards.rb +0 -398
- data/lib/hecks/fuzzing/properties/invariants_and_aggregation.rb +0 -399
- data/lib/hecks/fuzzing/properties/lifecycle_and_replay.rb +0 -137
- data/lib/hecks/fuzzing/properties/outbox.rb +0 -180
- data/lib/hecks/fuzzing/properties/querying.rb +0 -260
- data/lib/hecks/fuzzing/properties.rb +0 -267
- data/lib/hecks/fuzzing/qa_settings.rb +0 -164
- data/lib/hecks/fuzzing/replay.rb +0 -930
- data/lib/hecks/fuzzing/rotation_priority.rb +0 -114
- data/lib/hecks/fuzzing/rust_gap_manifest.rb +0 -139
- data/lib/hecks/fuzzing/self_consistency.rb +0 -825
- data/lib/hecks/fuzzing/sequence_generator/adversary.rb +0 -532
- data/lib/hecks/fuzzing/sequence_generator/catalog.rb +0 -171
- data/lib/hecks/fuzzing/sequence_generator/outcome_tracker.rb +0 -127
- data/lib/hecks/fuzzing/sequence_generator/picker.rb +0 -116
- data/lib/hecks/fuzzing/sequence_generator/query_binding.rb +0 -138
- data/lib/hecks/fuzzing/sequence_generator/step_builder.rb +0 -344
- data/lib/hecks/fuzzing/sequence_generator.rb +0 -311
- data/lib/hecks/fuzzing/shrinker.rb +0 -309
- data/lib/hecks/fuzzing/structural_skips.rb +0 -53
- data/lib/hecks/fuzzing/sweep_depth.rb +0 -61
- data/lib/hecks/fuzzing/target_capabilities.rb +0 -255
- data/lib/hecks/fuzzing/value_generator.rb +0 -340
- data/lib/hecks/fuzzing.rb +0 -23
- data/lib/hecks/grammar/evolve.rb +0 -524
- data/lib/hecks/query_ir.rb +0 -482
|
@@ -1,25 +1,7 @@
|
|
|
1
1
|
module Hecks
|
|
2
2
|
module Bluebook
|
|
3
|
-
#
|
|
4
|
-
#
|
|
5
|
-
# A `pattern:` is a fact about a value, carried in a bluebook — declared
|
|
6
|
-
# data, not Ruby code, so it must not lean on what any one engine happens
|
|
7
|
-
# to accept. Regex engines disagree in two different ways :
|
|
8
|
-
#
|
|
9
|
-
# only a backtracking engine can match it — lookahead, lookbehind,
|
|
10
|
-
# backreferences, atomic groups, possessive quantifiers. None of these
|
|
11
|
-
# can be matched in linear time, and linear-time engines refuse them
|
|
12
|
-
# outright. Refused here for the same reason.
|
|
13
|
-
#
|
|
14
|
-
# every engine parses it and they mean different things — the dangerous
|
|
15
|
-
# half, because nothing errors. `\d` `\w` `\s` are ASCII in some engines
|
|
16
|
-
# and Unicode in others ; `[:digit:]` and friends flip the same way in
|
|
17
|
-
# the other direction. Both families are refused, and a domain spells
|
|
18
|
-
# the range it means.
|
|
19
|
-
#
|
|
20
|
-
# What remains — explicit ranges, alternation, quantifiers, anchors,
|
|
21
|
-
# groups — reads identically everywhere, with `^` and `$` as line anchors
|
|
22
|
-
# (Ruby's reading). The evidence is spec/corpus/fixtures/patterns.json.
|
|
3
|
+
# Which regexes a bluebook `pattern:` may say: only what every engine reads the same way.
|
|
4
|
+
# Backtracking-only and ASCII/Unicode-dependent constructs are refused.
|
|
23
5
|
module PatternSubset
|
|
24
6
|
Rejection = Struct.new(:construct, :reason)
|
|
25
7
|
|
|
@@ -55,36 +37,19 @@ module Hecks
|
|
|
55
37
|
|
|
56
38
|
module_function
|
|
57
39
|
|
|
58
|
-
# nil when the pattern is admitted, a Rejection when it is not.
|
|
40
|
+
# Returns nil when the pattern is admitted, a Rejection when it is not.
|
|
59
41
|
#
|
|
60
|
-
#
|
|
61
|
-
#
|
|
62
|
-
# construct is a literal, not a violation — `\(\?=` is the three
|
|
63
|
-
# characters "(?=" and says nothing about lookahead — which is why this
|
|
64
|
-
# steps over each backslash pair rather than matching the pattern as a
|
|
65
|
-
# whole.
|
|
66
|
-
# One character walk is the subset's definition (see the method
|
|
67
|
-
# comment above): each construct-check is a branch in a single
|
|
68
|
-
# ordered pass sharing `index`/`in_class`/`class_start`. Splitting
|
|
69
|
-
# the branches into separate methods would force those three cursor
|
|
70
|
-
# variables to thread as parameters/return values between them,
|
|
71
|
-
# turning "the subset is this walk" into "the subset is these
|
|
72
|
-
# methods agreeing about a shared cursor" — exactly what the walk's
|
|
73
|
-
# own comment says a cleverer spelling would obscure.
|
|
42
|
+
# One ordered character walk defines the subset; an escaped construct is a literal,
|
|
43
|
+
# which is why each backslash pair is stepped over rather than matched as a whole.
|
|
74
44
|
# rubocop:disable-next Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
|
|
75
45
|
#
|
|
76
46
|
# @param pattern [String, Symbol, #to_s] the declared `pattern:` regex source
|
|
77
|
-
# @return [Rejection, nil] the reason the pattern is refused, or `nil` if
|
|
78
|
-
# entirely within the portable subset
|
|
47
|
+
# @return [Rejection, nil] the reason the pattern is refused, or `nil` if admitted
|
|
79
48
|
def validate(pattern)
|
|
80
49
|
chars = pattern.to_s.chars
|
|
81
50
|
index = 0
|
|
82
|
-
#
|
|
83
|
-
#
|
|
84
|
-
# group syntax — `[*+]` means "a literal asterisk or plus". `]` is
|
|
85
|
-
# only the class's close when it isn't the first character after `[`
|
|
86
|
-
# or `[^` (where it is itself a literal, per POSIX bracket-expression
|
|
87
|
-
# rules).
|
|
51
|
+
# Inside `[...]` quantifier characters are literals, and `]` closes the class unless
|
|
52
|
+
# it is the first character after `[` or `[^`.
|
|
88
53
|
in_class = false
|
|
89
54
|
class_start = nil
|
|
90
55
|
|
|
@@ -136,8 +101,7 @@ module Hecks
|
|
|
136
101
|
nil
|
|
137
102
|
end
|
|
138
103
|
|
|
139
|
-
# Spelled out, not derived from the key
|
|
140
|
-
# a caller reads.
|
|
104
|
+
# Spelled out, not derived from the key: callers read these strings in refusals.
|
|
141
105
|
CONSTRUCTS = {
|
|
142
106
|
backreference: "backreference",
|
|
143
107
|
named_backreference: "named backreference",
|
|
@@ -149,17 +113,8 @@ module Hecks
|
|
|
149
113
|
possessive: "possessive quantifier"
|
|
150
114
|
}.freeze
|
|
151
115
|
|
|
152
|
-
# Builds the rejection for one refused construct.
|
|
153
|
-
#
|
|
154
|
-
# @param key [Symbol] a key of `CONSTRUCTS`/`REASONS`, such as `:lookahead`
|
|
155
|
-
# @return [Rejection] the construct's name and the reason it is refused
|
|
156
116
|
def refuse(key) = Rejection.new(CONSTRUCTS.fetch(key), REASONS.fetch(key))
|
|
157
117
|
|
|
158
|
-
# Says whether a POSIX bracket class (`[:digit:]` and friends) starts at `index`.
|
|
159
|
-
#
|
|
160
|
-
# @param chars [Array<String>] the pattern, split into characters
|
|
161
|
-
# @param index [Integer] the position to check
|
|
162
|
-
# @return [Boolean] whether a POSIX bracket class starts at `index`
|
|
163
118
|
def posix_class_at?(chars, index)
|
|
164
119
|
return false unless chars[index] == "[" && chars[index + 1] == ":"
|
|
165
120
|
|
|
@@ -168,14 +123,7 @@ module Hecks
|
|
|
168
123
|
chars[cursor] == ":" && chars[cursor + 1] == "]"
|
|
169
124
|
end
|
|
170
125
|
|
|
171
|
-
# A possessive quantifier is `*+`, `++`,
|
|
172
|
-
# immediately followed by `+` — only checked outside a character class,
|
|
173
|
-
# where `*`, `+`, `?`, `{`, `}` are quantifier syntax rather than
|
|
174
|
-
# literal characters.
|
|
175
|
-
#
|
|
176
|
-
# @param chars [Array<String>] the pattern, split into characters
|
|
177
|
-
# @param index [Integer] the position to check
|
|
178
|
-
# @return [Boolean] whether a possessive quantifier starts at `index`
|
|
126
|
+
# A possessive quantifier is `*+`, `++`, `?+` or a `{n,m}` bound followed by `+`.
|
|
179
127
|
def possessive_at?(chars, index)
|
|
180
128
|
return true if %w[* + ?].include?(chars[index]) && chars[index + 1] == "+"
|
|
181
129
|
return false unless chars[index] == "{"
|
|
@@ -184,13 +132,7 @@ module Hecks
|
|
|
184
132
|
!len.nil? && chars[index + len] == "+"
|
|
185
133
|
end
|
|
186
134
|
|
|
187
|
-
# Length of a `{n}` / `{n,}` / `{n,m}` bound
|
|
188
|
-
# if what's there isn't one.
|
|
189
|
-
#
|
|
190
|
-
# @param chars [Array<String>] the pattern, split into characters
|
|
191
|
-
# @param index [Integer] the position the bound is expected to start at
|
|
192
|
-
# @return [Integer, nil] the bound's length in characters, or `nil` if `index`
|
|
193
|
-
# does not start a `{n}`/`{n,}`/`{n,m}` bound
|
|
135
|
+
# Length of a `{n}` / `{n,}` / `{n,m}` bound at `index`, or nil if there is none.
|
|
194
136
|
def bounded_quantifier_length(chars, index)
|
|
195
137
|
cursor = index + 1
|
|
196
138
|
digit_seen = false
|
|
@@ -3,19 +3,10 @@ require_relative "../ir"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Bluebook
|
|
6
|
-
# `compensates`
|
|
7
|
-
#
|
|
8
|
-
# (see `ProcessManagerBuilder::HandlerBuilder#dispatch_impl`'s own
|
|
9
|
-
# comment). `nil` for a dispatch with nothing to undo (a pure
|
|
10
|
-
# bookkeeping mark, or one whose own effect is superseded by a later
|
|
11
|
-
# command rather than needing its own compensation). Never nested
|
|
12
|
-
# further — a compensation is not itself compensable; no known
|
|
13
|
-
# corpus need, and ADR 0025's own "a word earns its place by being
|
|
14
|
-
# used" bar would refuse a second level speculatively.
|
|
6
|
+
# `compensates` is a second `DispatchSpec` naming the command that undoes this one, or nil.
|
|
7
|
+
# Never nested; `reverses` stays reserved for `corrects`.
|
|
15
8
|
DispatchSpec = Struct.new(:command_name, :with_spec, :compensates, keyword_init: true) do
|
|
16
|
-
#
|
|
17
|
-
# declared emission ahead of Struct's own in the ancestry, which
|
|
18
|
-
# is what makes the shape data rather than a method body.
|
|
9
|
+
# Struct already answers to_h; the mixin puts the declared emission ahead of it.
|
|
19
10
|
include Hecks::IR
|
|
20
11
|
|
|
21
12
|
emits_ir(
|
|
@@ -37,62 +28,19 @@ module Hecks
|
|
|
37
28
|
)
|
|
38
29
|
end
|
|
39
30
|
|
|
40
|
-
# The compensation half of a procedure
|
|
41
|
-
#
|
|
42
|
-
# A process manager coordinates: legs, states, an opinion about who goes
|
|
43
|
-
# next. A saga undoes: what makes the world good again when a leg it
|
|
44
|
-
# dispatched is refused. Two concepts, and the industry slurs them into one
|
|
45
|
-
# word — so here they are two objects, and a procedure either has a saga or
|
|
46
|
-
# does not.
|
|
47
|
-
#
|
|
48
|
-
# `undoes` is the ordered list of commands the compensation sends — a
|
|
49
|
-
# static preview, declaration order (`Behaviour::ProcessManager#saga`),
|
|
50
|
-
# not one instance's own runtime history. Per-dispatch compensation
|
|
51
|
-
# (`compensates`, on the step it compensates for) moved most of what
|
|
52
|
-
# a saga undoes off this leg's own hand-written body and onto
|
|
53
|
-
# whichever forward dispatch each one undoes — this reads every
|
|
54
|
-
# declared `compensates` across the whole saga first, then whatever
|
|
55
|
-
# this leg's own hand-written body still lists, for compensation
|
|
56
|
-
# that isn't expressible as "undo command X." which of a declared
|
|
57
|
-
# `compensates` actually fires for one instance, and in what order
|
|
58
|
-
# (newest-first, completed-legs-only), is `SagaInterpreter`'s own
|
|
59
|
-
# dynamic `completed_compensations` — a per-instance runtime fact
|
|
60
|
-
# this declaration-only object could never hold.
|
|
61
|
-
#
|
|
62
|
-
# **Naming collision, once flagged, now resolved** — `command`'s own
|
|
63
|
-
# `corrects event, reverses: true` (docs/implemented/decisions/0036-
|
|
64
|
-
# corrects-is-an-appended-fact-not-a-rewrite.md) already claimed
|
|
65
|
-
# `reverses` for a different meaning: auto-deriving a command's own
|
|
66
|
-
# corrective mutation from a past event, not a saga's own
|
|
67
|
-
# compensating leg from a past dispatch. This feature keeps
|
|
68
|
-
# `reverses` reserved for `corrects` and uses `compensates` for
|
|
69
|
-
# per-dispatch saga compensation instead — a deliberate choice, not
|
|
70
|
-
# an accidental collision.
|
|
31
|
+
# The compensation half of a procedure: the commands sent to undo a refused leg.
|
|
32
|
+
# `undoes` is a static declaration-order preview; per-instance order is the runtime's.
|
|
71
33
|
Saga = Struct.new(:trigger, :from_state, :to_state, :compensations, keyword_init: true) do
|
|
72
|
-
# Lists the commands this saga sends to undo a refused leg.
|
|
73
|
-
#
|
|
74
|
-
# @return [Array<String>] the name of each compensating command, in the order
|
|
75
|
-
# `compensations` lists them
|
|
76
34
|
def undoes = compensations.map(&:command_name)
|
|
77
35
|
|
|
78
36
|
def to_s = "#{trigger} → #{to_state} (#{undoes.join(', ')})"
|
|
79
37
|
end
|
|
80
38
|
|
|
81
|
-
# The built form of a `process_manager "Name" do ... end` block,
|
|
82
|
-
#
|
|
83
|
-
# correlation field, derived states, and handler rows. Its
|
|
84
|
-
# compensation half (`saga`, `Behaviour::ProcessManager#saga`) is
|
|
85
|
-
# derived from the handler answering `REFUSED`, below, not declared as
|
|
86
|
-
# its own construct.
|
|
39
|
+
# The built form of a `process_manager "Name" do ... end` block, made by
|
|
40
|
+
# `DSL::ProcessManagerBuilder`.
|
|
87
41
|
class ProcessManager
|
|
88
|
-
# The
|
|
89
|
-
#
|
|
90
|
-
# Construct when this one crosses.
|
|
91
|
-
# The trigger of a compensating leg. Not an event name — no aggregate
|
|
92
|
-
# announces that a leg the procedure dispatched was declined — so it lives
|
|
93
|
-
# here beside the thing it triggers rather than in the runtime that
|
|
94
|
-
# notices it. Declared in the language's Trigger vocabulary, which
|
|
95
|
-
# spec/vocabulary_conformance_spec holds to this constant.
|
|
42
|
+
# The trigger of a compensating leg. Not an event name: no aggregate announces a declined
|
|
43
|
+
# leg. Held to the language's Trigger vocabulary by spec/vocabulary_conformance_spec.
|
|
96
44
|
REFUSED = Hecks::Vocabulary.fetch("Trigger").first
|
|
97
45
|
|
|
98
46
|
include Hecks::IR
|
|
@@ -100,21 +48,8 @@ module Hecks
|
|
|
100
48
|
|
|
101
49
|
emits_ir(
|
|
102
50
|
name: :name,
|
|
103
|
-
#
|
|
104
|
-
#
|
|
105
|
-
# mint one without it), but the IR class itself defaults it to
|
|
106
|
-
# `nil` and is what `Assembly::Build`'s `:identity` reader
|
|
107
|
-
# (`value&.to_sym`) round-trips against. A bare `.to_s` mapped
|
|
108
|
-
# that absent case to `""`, indistinguishable on the wire from a
|
|
109
|
-
# real empty name and read back as the wrong, non-nil `:""`
|
|
110
|
-
# instead of `nil` — the same nil-erasure S1 fixed for
|
|
111
|
-
# `render_value`, one field over. `correlates_by` is always a
|
|
112
|
-
# bare Symbol (`SagaInterpreter` hash-looks-up a payload by it),
|
|
113
|
-
# never a `Literal`-encoded polymorphic value, so this stays a
|
|
114
|
-
# local `&.` rather than routing through `Literal.render` — that
|
|
115
|
-
# would wrap a real value in a leading `:` and break both the
|
|
116
|
-
# `:identity` reader's plain `to_sym` and the pinned golden IR
|
|
117
|
-
# fixtures' bare-string spelling (`"reference.value"`).
|
|
51
|
+
# `&.` because the IR class defaults `correlates_by` to nil; `.to_s` reads back as `""`.
|
|
52
|
+
# A bare Symbol string, not `Literal.render`, to match the golden IR fixtures.
|
|
118
53
|
correlates_by: -> { correlates_by&.to_s },
|
|
119
54
|
starts_on: :starts_on,
|
|
120
55
|
ends_on: :ends_on,
|
|
@@ -124,15 +59,10 @@ module Hecks
|
|
|
124
59
|
|
|
125
60
|
attr_reader :name, :correlates_by, :starts_on, :ends_on, :states, :handlers
|
|
126
61
|
|
|
127
|
-
# @param
|
|
128
|
-
#
|
|
129
|
-
# instances are correlated by
|
|
62
|
+
# @param correlates_by [Symbol, nil] the payload field that correlates a triggering
|
|
63
|
+
# event to an instance
|
|
130
64
|
# @param starts_on [String, nil] the event that starts a new instance
|
|
131
65
|
# @param ends_on [String, nil] the event that ends an instance
|
|
132
|
-
# @param states [Array<String>] the declared states this procedure's instances pass
|
|
133
|
-
# through
|
|
134
|
-
# @param handlers [Array<Bluebook::ProcessManagerHandler>] the declared handler rows,
|
|
135
|
-
# one per (event, state) leg
|
|
136
66
|
def initialize(name:, correlates_by: nil, starts_on: nil, ends_on: nil,
|
|
137
67
|
states: [], handlers: [])
|
|
138
68
|
@name = name.to_s
|
|
@@ -3,9 +3,8 @@ require_relative "project_register"
|
|
|
3
3
|
|
|
4
4
|
module Hecks
|
|
5
5
|
module Bluebook
|
|
6
|
-
# Boots each discovered directory and feeds its declarations into the
|
|
7
|
-
#
|
|
8
|
-
# their own objects so either can be used without executing domains.
|
|
6
|
+
# Boots each discovered directory and feeds its declarations into the project register.
|
|
7
|
+
# Discovery and FQN registration are separate objects so either works without booting domains.
|
|
9
8
|
class ProjectLoader
|
|
10
9
|
Entry = ProjectRegister::Entry
|
|
11
10
|
DuplicateFqn = ProjectRegister::DuplicateFqn
|
|
@@ -14,31 +13,15 @@ module Hecks
|
|
|
14
13
|
|
|
15
14
|
attr_reader :root, :discovery, :register
|
|
16
15
|
|
|
17
|
-
# Discovers and loads every domain under `root` in one call.
|
|
18
|
-
#
|
|
19
|
-
# @param root [String] the directory to search under
|
|
20
|
-
# @return [Bluebook::ProjectLoader] the loader, with every discovered domain
|
|
21
|
-
# booted and registered
|
|
22
16
|
def self.load(root) = new(root).load
|
|
23
17
|
|
|
24
|
-
# @param root [String] the directory to search under
|
|
25
|
-
# @param discovery [Bluebook::ProjectDiscovery] the discovery this loader walks
|
|
26
|
-
# `root` with
|
|
27
|
-
# @param register [Bluebook::ProjectRegister] the register booted domains are
|
|
28
|
-
# fed into
|
|
29
18
|
def initialize(root, discovery: ProjectDiscovery.new(root), register: ProjectRegister.new)
|
|
30
19
|
@root = File.expand_path(root)
|
|
31
20
|
@discovery = discovery
|
|
32
21
|
@register = register
|
|
33
22
|
end
|
|
34
23
|
|
|
35
|
-
#
|
|
36
|
-
#
|
|
37
|
-
# @return [Bluebook::ProjectLoader] self
|
|
38
|
-
# @raise [Bluebook::ProjectRegister::MissingRealm] see `ProjectRegister#register`
|
|
39
|
-
# @raise [Bluebook::ProjectRegister::LatestMismatch] see `ProjectRegister#register`
|
|
40
|
-
# @raise [Bluebook::ProjectRegister::DuplicateFqn] see `ProjectRegister#register`
|
|
41
|
-
# @raise [Runtime::WiringError] see `ProjectRegister#register`
|
|
24
|
+
# Errors raised by `ProjectRegister#register` propagate.
|
|
42
25
|
def load
|
|
43
26
|
discovery.bluebook_directories.each do |directory|
|
|
44
27
|
runtime = Runtime.boot(directory)
|
|
@@ -47,33 +30,14 @@ module Hecks
|
|
|
47
30
|
self
|
|
48
31
|
end
|
|
49
32
|
|
|
50
|
-
# Lists every registered entry.
|
|
51
|
-
#
|
|
52
|
-
# @return [Hash{String => Bluebook::ProjectRegister::Entry}] every registered
|
|
53
|
-
# entry, keyed by its FQN
|
|
54
33
|
def entries = register.entries
|
|
55
34
|
|
|
56
|
-
# Finds a registered entry by its fully-qualified verb.
|
|
57
|
-
#
|
|
58
|
-
# @param address [String, #to_s] the FQN to look up
|
|
59
|
-
# @return [Bluebook::ProjectRegister::Entry] the entry registered under `address`
|
|
60
|
-
# @raise [KeyError] if no entry is registered under `address`
|
|
61
35
|
def fetch(address) = register.fetch(address)
|
|
62
36
|
|
|
63
|
-
# Says whether an entry is registered under an address.
|
|
64
|
-
#
|
|
65
|
-
# @param address [String, #to_s] the FQN to check
|
|
66
|
-
# @return [Boolean] whether an entry is registered under `address`
|
|
67
37
|
def include?(address) = register.include?(address)
|
|
68
38
|
|
|
69
|
-
# Lists every registered command entry.
|
|
70
|
-
#
|
|
71
|
-
# @return [Array<Bluebook::ProjectRegister::Entry>] every registered command entry
|
|
72
39
|
def commands = register.commands
|
|
73
40
|
|
|
74
|
-
# Lists every registered query entry.
|
|
75
|
-
#
|
|
76
|
-
# @return [Array<Bluebook::ProjectRegister::Entry>] every registered query entry
|
|
77
41
|
def queries = register.queries
|
|
78
42
|
end
|
|
79
43
|
end
|
|
@@ -4,14 +4,8 @@ module Hecks
|
|
|
4
4
|
# declarations become public FQNs, but never searches or boots folders.
|
|
5
5
|
class ProjectRegister
|
|
6
6
|
Entry = Struct.new(:fqn, :source_directory, :dispatcher, :declared_verb, :domain_version, keyword_init: true) do
|
|
7
|
-
# Says whether this entry addresses a command.
|
|
8
|
-
#
|
|
9
|
-
# @return [Boolean] whether this entry's `fqn` addresses a command
|
|
10
7
|
def command? = fqn.command?
|
|
11
8
|
|
|
12
|
-
# Says whether this entry addresses a query.
|
|
13
|
-
#
|
|
14
|
-
# @return [Boolean] whether this entry's `fqn` addresses a query
|
|
15
9
|
def query? = fqn.query?
|
|
16
10
|
end
|
|
17
11
|
|
|
@@ -21,53 +15,31 @@ module Hecks
|
|
|
21
15
|
|
|
22
16
|
attr_reader :entries
|
|
23
17
|
|
|
24
|
-
# Starts an empty register, with no domains loaded yet.
|
|
25
18
|
def initialize
|
|
26
19
|
@entries = {}
|
|
27
20
|
@tenant_directories = Hash.new { |hash, key| hash[key] = [] }
|
|
28
21
|
end
|
|
29
22
|
|
|
30
|
-
# Finds
|
|
23
|
+
# Finds an entry by FQN, such as `"Pizzas.Pizza.Order"`.
|
|
31
24
|
#
|
|
32
|
-
# @param address [String, #to_s] the FQN to look up, such as `"Pizzas.Pizza.Order"`
|
|
33
|
-
# @return [Bluebook::ProjectRegister::Entry] the entry registered under `address`
|
|
34
25
|
# @raise [KeyError] if no entry is registered under `address`
|
|
35
26
|
def fetch(address) = entries.fetch(address.to_s)
|
|
36
27
|
|
|
37
|
-
# Says whether an entry is registered under an address.
|
|
38
|
-
#
|
|
39
|
-
# @param address [String, #to_s] the FQN to check
|
|
40
|
-
# @return [Boolean] whether an entry is registered under `address`
|
|
41
28
|
def include?(address) = entries.key?(address.to_s)
|
|
42
29
|
|
|
43
|
-
# Lists every registered command entry.
|
|
44
|
-
#
|
|
45
|
-
# @return [Array<Bluebook::ProjectRegister::Entry>] every registered command entry
|
|
46
30
|
def commands = entries.values.select(&:command?)
|
|
47
31
|
|
|
48
|
-
|
|
49
|
-
#
|
|
50
|
-
# @return [Array<Bluebook::ProjectRegister::Entry>] every registered query entry
|
|
51
|
-
def queries = entries.values.select(&:query?)
|
|
32
|
+
def queries = entries.values.select(&:query?)
|
|
52
33
|
|
|
53
|
-
# Registers every aggregate command/query and read model query
|
|
54
|
-
#
|
|
34
|
+
# Registers every aggregate command/query and read model query of each chapter, under
|
|
35
|
+
# its versioned and (if current) unversioned FQNs.
|
|
55
36
|
#
|
|
56
|
-
# @param bluebooks [Array<Bluebook::Chapter>] the booted chapters to register
|
|
57
|
-
# @param registry [Runtime::Registry] the registry `bluebooks` booted into
|
|
58
|
-
# @param dispatcher [Runtime::Dispatcher, Runtime::RemoteDispatcher] the booted
|
|
59
|
-
# dispatcher entries dispatch through
|
|
60
|
-
# @param directory [String] the source directory `bluebooks` was discovered under
|
|
61
37
|
# @return [Bluebook::ProjectRegister] self
|
|
62
|
-
# @raise [
|
|
63
|
-
#
|
|
64
|
-
# @raise [
|
|
65
|
-
#
|
|
66
|
-
#
|
|
67
|
-
# is already registered
|
|
68
|
-
# @raise [Runtime::WiringError] if a second tenant registers the same on-disk
|
|
69
|
-
# directory while any of its aggregates binds to an adapter that is not
|
|
70
|
-
# `tenant_capable?`
|
|
38
|
+
# @raise [MissingRealm] if a bluebook's world declares no realm
|
|
39
|
+
# @raise [LatestMismatch] if a world's `latest` disagrees with its bluebook's version
|
|
40
|
+
# @raise [DuplicateFqn] if an FQN this call would register is already registered
|
|
41
|
+
# @raise [Runtime::WiringError] if a second tenant registers the same directory while
|
|
42
|
+
# an aggregate binds to an adapter that is not `tenant_capable?`
|
|
71
43
|
def register(bluebooks, registry, dispatcher, directory)
|
|
72
44
|
bluebooks.each do |bluebook|
|
|
73
45
|
refuse_unless_safe_for_second_tenant!(bluebook, registry, directory)
|
|
@@ -87,10 +59,6 @@ module Hecks
|
|
|
87
59
|
|
|
88
60
|
private
|
|
89
61
|
|
|
90
|
-
# Split out of `register` per-aggregate: same versioned-then-current
|
|
91
|
-
# registration shape as `register_read_model!`, just applied to a
|
|
92
|
-
# command/query pair instead of a single report. No state threads
|
|
93
|
-
# back to `register` — each `add` call is independent.
|
|
94
62
|
def register_aggregate!(aggregate, bluebook, world, realm, directory, dispatcher)
|
|
95
63
|
aggregate.commands.each do |command|
|
|
96
64
|
if bluebook.version
|
|
@@ -116,9 +84,6 @@ module Hecks
|
|
|
116
84
|
end
|
|
117
85
|
end
|
|
118
86
|
|
|
119
|
-
# Split out of `register` per-read-model: registers the versioned FQN
|
|
120
|
-
# (if this bluebook declares a version) and the current/unversioned
|
|
121
|
-
# FQN (if this bluebook is the world's latest) for one report.
|
|
122
87
|
def register_read_model!(model, bluebook, world, realm, directory, dispatcher)
|
|
123
88
|
if bluebook.version
|
|
124
89
|
add(Fqn.query(realm: realm, domain: bluebook.name, version: bluebook.version,
|
|
@@ -130,22 +95,9 @@ module Hecks
|
|
|
130
95
|
end
|
|
131
96
|
end
|
|
132
97
|
|
|
133
|
-
#
|
|
134
|
-
#
|
|
135
|
-
#
|
|
136
|
-
# `persisted_by` binding) registering a second time, under a
|
|
137
|
-
# different realm, into this same shared route table. A directory's
|
|
138
|
-
# first registration is never refused here — nothing shares its
|
|
139
|
-
# data yet, so a plain single-tenant deployment on an ordinary
|
|
140
|
-
# adapter (Postgres, no schema story) still boots exactly as
|
|
141
|
-
# before. Only the second (and any later) registration of that
|
|
142
|
-
# same directory is refused, and refused before this call adds its
|
|
143
|
-
# routes to the table — so a leaking tenant's requests never
|
|
144
|
-
# become reachable through `Router#resolve` in the first place.
|
|
145
|
-
#
|
|
146
|
-
# Keyed on `directory` + `bluebook.name` only, not realm or
|
|
147
|
-
# `dispatcher` — two tenants share the identical on-disk domain,
|
|
148
|
-
# differing only by which realm/environment overlay booted it.
|
|
98
|
+
# A directory's first registration is never refused; only a second one (another tenant
|
|
99
|
+
# sharing the on-disk domain) is, before its routes reach the table. Keyed on
|
|
100
|
+
# `directory` + name, not realm or dispatcher.
|
|
149
101
|
def refuse_unless_safe_for_second_tenant!(bluebook, registry, directory)
|
|
150
102
|
key = [directory, bluebook.name]
|
|
151
103
|
seen_before = @tenant_directories.key?(key) && @tenant_directories[key].any?
|
data/lib/hecks/bluebook/query.rb
CHANGED
|
@@ -1,33 +1,15 @@
|
|
|
1
1
|
require_relative "behaviour/query"
|
|
2
2
|
|
|
3
3
|
module Hecks
|
|
4
|
-
# Reopened
|
|
5
|
-
# wire-literal rendering (`Literal.render`) the `emits_ir` Procs
|
|
6
|
-
# throughout this chapter reach for. See lib/hecks/bluebook.rb's own
|
|
7
|
-
# header for what `Bluebook` is as a whole.
|
|
4
|
+
# Reopened to add `render_value`, the wire-literal rendering `emits_ir` procs use.
|
|
8
5
|
module Bluebook
|
|
9
|
-
# Renders a captured
|
|
10
|
-
#
|
|
11
|
-
# @param value [Object] any value an `emits_ir` field carries, such as a Symbol,
|
|
12
|
-
# String, Hash, Array, or literal
|
|
13
|
-
# @return [String] the value rendered through `Hecks::Literal.render`
|
|
6
|
+
# Renders a captured value to its wire spelling through `Hecks::Literal.render`.
|
|
14
7
|
def self.render_value(value) = Literal.render(value)
|
|
15
8
|
|
|
16
9
|
# A query — an ask, declared on an aggregate or on one of its entities.
|
|
17
10
|
#
|
|
18
|
-
# It crosses over as an instance
|
|
19
|
-
#
|
|
20
|
-
# whole body from `QuerySpecification::Common::Options` — `wheres`,
|
|
21
|
-
# `order_by`, `limit`, `offset`, `cursor`,
|
|
22
|
-
# `authorization`, `null_semantics`, `inspection` — and those
|
|
23
|
-
# are instance methods that the runtime and the SQLite adapter both read.
|
|
24
|
-
# Hoisting the declaration onto a metaclass would put the identity and the
|
|
25
|
-
# specification on opposite sides of the object.
|
|
26
|
-
#
|
|
27
|
-
# And nothing is lost, because `Class#name` was the only reason a construct
|
|
28
|
-
# ever needed a second word for its own name. An instance answers `name`
|
|
29
|
-
# truthfully. So a query gains an owner and an identity — which is what the
|
|
30
|
-
# graph is for — and keeps the name it always had.
|
|
11
|
+
# It crosses over as an instance, not a class: its body comes from
|
|
12
|
+
# `QuerySpecification::Common::Options`, whose instance methods the runtime reads.
|
|
31
13
|
class Query < QuerySpecification::Common::Options
|
|
32
14
|
include Construct
|
|
33
15
|
|
|
@@ -45,25 +27,8 @@ module Hecks
|
|
|
45
27
|
|
|
46
28
|
attr_reader :name, :description, :attributes
|
|
47
29
|
|
|
48
|
-
# @param
|
|
49
|
-
#
|
|
50
|
-
# @param attributes [Array<Bluebook::Attribute>] the query's declared result fields
|
|
51
|
-
# @param wheres [Array<QuerySpecification::Common::WhereClause>] the declared filter
|
|
52
|
-
# conditions
|
|
53
|
-
# @param order_by [QuerySpecification::Common::OrderBy, nil] the declared sort field
|
|
54
|
-
# and direction, or `nil` for no explicit ordering
|
|
55
|
-
# @param limit [QuerySpecification::Common::LimitSpec, nil] the declared row limit,
|
|
56
|
-
# or `nil` for none
|
|
57
|
-
# @param offset [QuerySpecification::Common::OffsetSpec, nil] the declared row offset,
|
|
58
|
-
# or `nil` for none
|
|
59
|
-
# @param cursor [QuerySpecification::Common::CursorSpec, nil] the declared pagination
|
|
60
|
-
# cursor, or `nil` for none
|
|
61
|
-
# @param authorization [QuerySpecification::Common::AuthorizationSpec, nil] the declared
|
|
62
|
-
# authorization policy, or `nil` for none
|
|
63
|
-
# @param null_semantics [QuerySpecification::Common::NullSemantics, nil] how this query
|
|
64
|
-
# orders `nil` values; defaults to `NullSemantics.default` when omitted
|
|
65
|
-
# @param inspection [QuerySpecification::Common::InspectionSpec, nil] the declared
|
|
66
|
-
# inspection mode, or `nil` for none
|
|
30
|
+
# @param null_semantics [QuerySpecification::Common::NullSemantics, nil] defaults to
|
|
31
|
+
# `NullSemantics.default`
|
|
67
32
|
def initialize(name:, description: nil, attributes: [], wheres: [],
|
|
68
33
|
order_by: nil, limit: nil, offset: nil, cursor: nil,
|
|
69
34
|
authorization: nil, null_semantics: nil,
|
|
@@ -78,14 +43,10 @@ module Hecks
|
|
|
78
43
|
@attributes = attributes
|
|
79
44
|
end
|
|
80
45
|
|
|
81
|
-
#
|
|
82
|
-
#
|
|
83
|
-
# group_by, scope_to). Declared emission covers the settled part
|
|
84
|
-
# and `super` hands it over; the tail stays dynamic, which is the
|
|
85
|
-
# honest description of it.
|
|
46
|
+
# `extra_options_to_h` (count, median, group_by, scope_to) stays dynamic; `super` covers the
|
|
47
|
+
# declared emission.
|
|
86
48
|
#
|
|
87
|
-
# @return [Hash] the declared emission
|
|
88
|
-
# the specification layer currently carries
|
|
49
|
+
# @return [Hash] the declared emission merged with `extra_options_to_h`
|
|
89
50
|
def to_h = super.merge(extra_options_to_h)
|
|
90
51
|
end
|
|
91
52
|
end
|